Reputation: 21
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!
Upvotes: 2
Views: 1302
Reputation: 25833
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)
Upvotes: 1