简体   繁体   中英

shell command fails with subprocess.call() in Python

I'm failing to run a shell command from a python script using subprocess.call(). The test below works if I copy the python output and paste into the shell but not when I call the command via subprocess.call(). Can Anyone throw some light on my error/thinking please? I am just starting with Programming and think this is a "can't see the wood for the trees" thing, there are other posts about this but I can not apply them to my problem.

I think the shell script is not getting its arguments. I have set shell=True and tried ' and " around args with whitespaces.

import subprocess as s

fromCall = 'MB7UZ-1'
toCall = 'APRS'
path = 'via WIDE1-1'
ax25Port = 'aprs'
command = "/sbin/beacon"
packet = ":Test Beacon 4"

command_args = "-c '{0}' -d '{1} {2}' -s {3} '{4}'".format(fromCall, toCall, path, ax25Port, packet)

s.call([command, command_args], shell=True)
print repr(command_args)

prints the following to the console

/sbin/beacon -c MB7UZ-1 -d 'APRS via WIDE1-1' -s aprs ':Test Beacon 4'

If I copy that whole line and paste back into the shell the /sbin/beacon program works as expected.

I have searched extensively here and Google, some posts suggest converting the arguments to UTF-8 ...

Python 2.7.3 (default, Feb 27 2013, 13:38:49)
[GCC 4.7.2 20120921 (Red Hat 4.7.2-2)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import locale ; locale.getdefaultlocale()
('en_US', 'UTF-8')

... I don't think this is the problem given the output above but somehow still find myself mentioning it!

The argument to s.call should look like this: [command, "arg1", "arg2", "arg3", ...] , you're passing [command, "arg1 arg2 arg3"] so /sbin/beacon is only getting one argument which is:

-c MB7UZ-1 -d 'APRS via WIDE1-1' -s aprs ':Test Beacon 4'

You have two options, the better one is to split up the arguments. Something like:

import subprocess as s

fromCall = 'MB7UZ-1'
toCall = 'APRS'
path = 'via WIDE1-1'
ax25Port = 'aprs'
command = "/sbin/beacon"
packet = ":Test Beacon 4"

command = ["/sbin/beacon", "-c", fromCall, "-d", " ".join((toCall, path)), "-s",
           ax25Port, packet]
s.call(command)

Or the option I like less, pass a single string to s.call and let the shell split the arguments for you. You can only do this if you use shell=True .

import subprocess as s

fromCall = 'MB7UZ-1'
toCall = 'APRS'
path = 'via WIDE1-1'
ax25Port = 'aprs'
command = "/sbin/beacon"
packet = ":Test Beacon 4"

command = command + " -c '{0}' -d '{1} {2}' -s {3} '{4}'".format(fromCall, toCall, path, ax25Port, packet)

s.call(command, shell=True)
print repr(command)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM