Can I use an alias to execute a program from a python script

*爱你&永不变心* 提交于 2019-12-17 19:16:13

问题


I am almost brand new to python scripting, so please excuse any stupid questions, but any help anyone can give would be much appreciated.

I am trying to write a python script for other people to use, and in it I need to call a program that I won't always know the path to. To get around that, I ask the user to provide the path to the program, which will work, but I don't want users to have to provide the path EVERY time they run the script so I have been trying to set up a bash alias by having the script add to the ~/.profile and ~/.bashrc files.

I can then use the alias to run the program from an interactive bash shell, but when the script tries to run it, I get a "command not found" error...

I have tried re-sourcing the .bashrc file and using the "shopt -s expand_aliases" command with no luck.

My ~/.bashrc looks like this:

alias nuke='/Applications/Nuke6.2v4/Nuke6.2v4.app/Contents/MacOS/Nuke6.2v4'

And the piece of the script looks like this:

os.system('source .bashrc')
os.system('shopt -s expand_aliases')
os.system('nuke -x scriptPath')

But once the script gets up to this point, it returns:

sh: nuke: command not found

Am I doing something wrong or is there another way I can permanently store the path to a program?


回答1:


The module you want is subprocess.

A quick fix to your problem is to use the subprocess module, like so:

import subprocess
sp = subprocess.Popen(["/bin/bash", "-i", "-c", "nuke -x scriptpath"])
sp.communicate()

This is equivalent to calling:

nuke -x scriptpath

from the bash shell. The -i flag tells bash to behave as though it's an interactive session (and use the ~/.bashrc file)

BUT, you should be really really careful you're not opening yourself up to any shell injection (for instance, if this command is called from a CGI page)

For quick scipts that users invoke directly from the shell they probably can't do any more damage than they could with general shell access, but if this script is called by a web page a malicious user could pass something a bit like "rm -dfr ~/ &" as the program.*

If the number of executables is small, you might be better off either naming them in the script:

PROGRAMS = {"nuke": "/path/to/nuke"
                "foo" : "/path/to/foo" }

# Parse command line args
program = sys.argv[1] 

sp = subprocess.Popen([PROGRAMS[program], "other", "arguments", "to", "program"])

*This might not work exactly like this, but you get the idea




回答2:


Be aware that os.system is probably using sh rather than bash, and so source and shopt will fail as well.

If it is using bash, it will fail as os.system creates a new process for each call. You could do it in one line like this:

os.system('source .bashrc; shopt -s expand_aliases; nuke -x scriptPath')

But you are by far best to get the path in some other way (or even read it from .bashrc manually if you want) and then use subprocess.Popen().




回答3:


I know this is an old question, but for anyone else who comes across this in the future, I think it's worth mentioning that modifying someone's ~/.bashrc or ~/.profile files (especially silently) is one of those ideas that generally falls under the umbrella of "bad practice". Additionally, it seems a bit heavy-handed for the problem you need to solve.

Instead, why not have your script keep track of its own configuration file stored in the user's home directory? It would be quite simple to do this using ConfigParser, your own JSON structure dumped to a file, or something else entirely if you want.

Then in your script, you can first check if it exists, and if it does, see if it contains the key you're looking for that holds the executable path. If either of those tests fail, you know you need to prompt the user for the path, at which point you can write it to the config file for next time.




回答4:


Yeah don't do that. Write your configuration out into your own dotfile, and don't use os.system, use subprocess.




回答5:


I think an alias is a very complicated and not greatly intuitive way of using the shell environment. How about using environment variables instead? That's basically what they're for...

Instead of asking your users to define an alias nuke, ask them to define an environment variable $NUKE. This save you from messing with .bashrc or any other configuration file. If the user adds export NUKE=<path> to their .bashrc it is automatically available in the environment when executing the python script interactively.

If you only need this path to make a system call, just use os.system('$NUKE -x scriptPath').

If you need the value in python, it is easy to access as well: after import os, os.environ gives you a dictionary of all environment variables currently defined. Getting the value an alias is set to on the contrary is very cumbersome in python.



来源:https://stackoverflow.com/questions/6856119/can-i-use-an-alias-to-execute-a-program-from-a-python-script

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!