TomSelleck
TomSelleck

Reputation: 6968

Platform independent example of subprocess.Popen

I have the following piece of code which needs to be platform independent which isn't at the moment:

This works in windows to start the python script "pb_cli.py"

proc = subprocess.Popen(["python","pb_cli.py","get_token","60"], stdout=subprocess.PIPE, shell=True, cwd = '.',)
(result, err) = proc.communicate()

However - this does not seem to work in Linux. In Linux, I need to do this:

proc = subprocess.Popen(["python pb_cli.py get_token 60"], stdout=subprocess.PIPE, shell=True, cwd = '.',)
(result, err) = proc.communicate()

When I try to use the Linux version on windows, I get the following error:

C:\Users\Documents\Code\STAGE\cli>python move_users.py --input=users.txt --username --source_account=531 --destination_account=9
'"python pb_cli.py get_token 60"' is not recognized as an internal or external command, operable program or batch file.

When I try to use the Windows version on Linux, it just starts the interpretor.

Anybody have any idea on how to make this code uniform across platforms?

Upvotes: 4

Views: 977

Answers (1)

unutbu
unutbu

Reputation: 880429

For any OS, when shell=False (which it is by default), the first argument should be a list:

Popen(["python","pb_cli.py","get_token","60"], stdout=subprocess.PIPE)

When shell=True, the first argument should be a string:

subprocess.Popen("python pb_cli.py get_token 60", shell=True, stdout=subprocess.PIPE)

PS. Try to avoid using shell=True since it can be a security risk.


The actual rule is a bit more complicated. The docs say,

If passing a single string, either shell must be True (see below) or else the string must simply name the program to be executed without specifying any arguments.

which implies that you can pass a string when shell=False as long at it is simply the name of the program to be executed. However, if you stick to the above rule, you won't go wrong.

Upvotes: 2

Related Questions