views:

51

answers:

2

I am having a problem converting one of my company's scripts from csh to Python. The csh script calls an aliased command, but when I call that same aliased command via os.system(), it does not work.

So, if foo is the aliased command:

CSH Script (this works, executes foo):

foo <argument>

Python (this does not work, error claims foo is an unknown command):

os.system("foo <argument>")

I figure there must be some kind of context switch happening when I execute the python script, which causes Python to not have access to the aliases created in the shell. After reading the documentation, it seems that os.system is being deprecated in favor of subprocess, and that subprocess has a shell parameter that might be able to help me out...problem is that I'm stuck using Python 2.3, and subprocess isn't available until version 2.4.

I had the idea to replicate the alias in python. So, for example, say foo was aliased to cp.

CSH:

alias foo cp
foo file1 file2

Python:

os.system("alias foo cp")
os.system("foo file1 file2")

No dice...errors here as well:

sh: line 0: alias: foo: not found
sh: line 0: alias: cp: not found
sh: foo: command not found

My last ditch effort is to take the few lines of code that use foo and put them into their own CSH script that Python would call. But if there's a way to make this work without resorting to that, I'd love to know about it.

Thanks in advance!

A: 

If you are willing to have the "foo" alias in Python, then perform the aliasing yourself before calling os.system:

cmd = "foo file1 file2"
foo_alias = "cp"

cmd = re.sub("^foo ", foo_alias + " ", cmd)
os.system(cmd)

If the foo alias is more elaborate (with argument substitution, etc), this could be more difficult.

Ned Batchelder
+4  A: 

What made you think os.system would use csh? It uses standard C function system, that on Unix system will call just basic /bin/sh. This will not be csh, but most probably bash, or some simpler version of it.

BTW: note that what you do with shell environment in os.system will not affect subsequent calls to os.system, because each is run in different subshell. In other words, changes made to the environment are lost. And your call to alias fails, because /bin/sh uses different syntax for aliases than csh.

You could workaround this by running not foo, but something along the lines:

os.system("/bin/csh -i -c 'foo arg1 arg2'")

Note the option -i which is supposed to force csh to read startup scripts.

Piotr Kalinowski
"What made you think os.system would use csh?"Ignorance? :) I thought it just passed a string to the command line.Thanks for the answer. This fixes the problem I was having, but unfortunately since every call runs in its own subshell, I'm going to have to figure out a different solution altogether. The nature of my `foo` command is such that it loads a bunch of other stuff to be used by your script, so if that stuff gets lost as soon as the os.system command finishes, then it won't work.
Axel Aguado
It does pass the stuff to the command line. It's just that there is no single *type* of command line ;) If it loads other stuff for subsequent commands, and you're converting the whole thing to python, perhaps you should convert that other stuff to python first ;)
Piotr Kalinowski