I am writing a python script (Linux) that is adding some shell aliases (writes them to HOME/.bash_aliases
).
In order to make an alias available immediately after it was written I should issue the following bash built-in:
source HOME/.bashrc
source
is a bash built-in so I cannot just:
os.system(source HOME/.bashrc)
If i try something like:
os.system('/bin/bash -c source HOME/.bashrc')
...will freeze the script (just like is waiting for something).
Any suggestions ?
What you want is not possible. A program (your script) cannot modify the environment of the caller (the shell you run it from).
Another approach which would allow you to do something close is to write it in terms of a bash function, which is run in the same process and can modify the caller. Note that sourcing during runtime can have possible negative side-effects depending on what the user has in their bashrc.
what you are trying to do is impossible. or better: how you are trying to do it is impossible.
your bash command is wrong. bash -s command
does not execute command
. it just stores the string "command" in the variable $1
and then drops you to the prompt. that is why the python script seems to freeze. what you meant to do is bash -c command
.
why do you source .bashrc
? would it not be enough to just source .bash_aliases
?
even if you got your bash command right, the changes will only take effect in the bash session started from python. once that bash session is closed, and your python script is done, you are back at your original bash session. all changes in the bash session started from python is lost.
everytime you want to change something in the current bash session, you have to do it from inside the current bash session. most of the commands you run from bash (system commands, python scripts, even bash scripts) will spawn another process, and everything you do in that other process will not affect your first bash session.
source
is a bash builtin which allows you to execute commands inside the currently running bash session, instead of spawning another process and running the commands there. defining a bash function is another way to execute commands inside the currently running bash session.
see this answer for more information about sourcing and executing.
what you can do to achieve what you want
modify your python script to just do the changes necessary to .bash_aliases
.
prepare a bash script to run your python script and then source .bash_aliases
.
#i am a bash script, but you have to source me, do not execute me.
modify_bash_aliases.py "$@"
source ~/.bash_aliases
add an alias to your .bashrc
to source that script
alias add_alias='source modify_bash_aliases.sh'
now when you type add_alias some_alias
in your bash prompt it will be replaced with source modify_bash_aliases.sh
and then executed. since source
is a bash builtin, the commands inside the script will be executed inside the currently running bash session. the python script will still run in another process, but the subsequent source
command will run inside your currently running bash session.
another way
modify your python script to just do the changes necessary to .bash_aliases
.
prepare a bash function to run your python script and then source .bash_aliases
.
add_alias() {
modify_bash_aliases.py "$@"
source ~/.bash_aliases
}
now you can call the function like this: add_alias some_alias
[[working solution]]
http://stackoverflow.com/questions/6856119/can-i-use-an-alias-to-execute-a-program-from-a-python-script
import subprocess
sp = subprocess.Popen(["/bin/bash", "-i", "-c", "nuke -x scriptpath"])
sp.communicate()
I had an interesting issue where I needed to source an RC file to get the correct output in my python script.
I eventually used this inside my function to bring over the same variables from the bash file I needed to source. Be sure to have os imported.
with open('overcloudrc') as data:
lines = data.readlines()
for line in lines:
var = line.split(' ')[1].split('=')[0].strip()
val = line.split(' ')[1].split('=')[1].strip()
os.environ[var] = val