Search code examples
pythonmacospython-3.xpopen

Some subShell problems with python3


Well, I'm trying to using a python3 script to manage my aliases on my MAC OS X. At first I've put all alias commands in a single file and try to use below code to turn on/off these alias:

def enable_alias(self):
    alias_controller = AliasListControl() # just a simple class to handle the single file path and other unimportant things.
    os.popen('cp ~/.bash_aliases ~/.bash_aliases.bak')
    os.popen('cat ' + alias_controller.path + '>> ~/.bash_aliases')
    os.system('source ~/.bash_aliases')

def disable_alias(self):
    os.popen('mv ~/.bash_aliases.bak ~/.bash_aliases')
    os.popen('source ~/.bash_aliases')# maybe I should call some other unalias commands there 

As you see, there exists an problem. When the script runs to os.system('source ~/.bash_aliases'), it will first open A subshell and execute the command, so the source operation will only take effect in the subshell, not the parent shell, then the command finished and the subshell was closed. This means what os.system('source ~/.bash_aliases') has done is just in vein.


Solution

  • It doesn't address your process problem, but an alternative is to put your commands either into shell scripts or into function definitions that are defined in your ~/.bash_profile.

    For example, as a script:

    Create the file enable_alias.sh:

    filename=$1
    cp ~/.bash_aliases ~/.bash_aliases.bak
    # If you use `cat` here, your aliases file will keep getting longer and longer with repeated definitions...  think you want to use > not >>
    cp /path/to/$1.txt ~/.bash_aliases    
    source ~/.bash_aliases
    

    Put this file somewhere in a folder in your PATH and make it executable. Then run it as:

    enable_alias.sh A
    

    ..where your file of settings, etc is called A.txt. The $1 will pass the first value as the file name.

    Or alternatively, you could do it as a function, and add that definition to your .bash_profile. (Functions can also take $1 when called.)

    disable_alias(){
        mv ~/.bash_aliases.bak ~/.bash_aliases
        source ~/.bash_aliases
    }
    

    As you say, it might be a good idea to put unalias commands into your .bash_aliases file as well. It might also be simpler to have copies of aliases as their own files A.txt B.txt etc and just cp A.txt ~/.bash_aliases with the enable command and not use the disable command at all (disable is equivalent to enabling file B.txt, for example.)

    Just some thoughts on another approach that is more 'bash-like'...