How do I run a command with string formatting? - python

I am using the subprocess module to run a command in python. But the problem is that I also want to include a string (for a file name) in the command.
An example of what I want to do:
from subprocess import call
command = "cd/DirectoryName"
call = [(command)]
In this specific example I want DirectoryName to be a variable determined by the user.
What I have tried to no avail:
Desktop=raw_input()
cmd="'cd %s'(Desktop/)"
call([cmd])
Here's the error I get when I try to run these commands in the python shell.
Chicken='Chicken'
command = 'say %s' % (Chicken)
print command
say Chicken
call([command])
Traceback (most recent call last):
File "/Applications/WingIDE.app/Contents/MacOS/src/debug/tserver/_sandbox.py", line 1, in <module>
# Used internally for debug sandbox under external interpreter
File "/Library/Frameworks/EPD64.framework/Versions/7.2/lib/python2.7/subprocess.py", line 493, in call
return Popen(*popenargs, **kwargs).wait()
File "/Library/Frameworks/EPD64.framework/Versions/7.2/lib/python2.7/subprocess.py", line 679, in __init__
errread, errwrite)
File "/Library/Frameworks/EPD64.framework/Versions/7.2/lib/python2.7/subprocess.py", line 1228, in _execute_child
raise child_exception
OSError: [Errno 2] No such file or directory
Just tried this and it made the shell crash.
Chicken="Chicken"
print Chicken
Chicken
call[("say %s" % (Chicken)]

That's not how string interpolation works.
cmd='cd %s' % (Desktop,)

First off,
cmd="'cd %s'(Desktop/)"
Doesn't seem like it would "printf" the %s.
Maybe
cmd="'cd %s/'%(Desktop)"
But I still don't know if that will interpolate since it's inside a string can using the "call" function and a python command -- wouldn't that call it on the command line?

Related

using Python to send subprocess commands with escape characters

I'm using a python script which uses subprocess to pass a commmand to the terminal. Part of the command that I'm passing involves paths which contain parentheses. Python handles strings with parentheses fine, but of course terminal does not handle these without escape characters.
I'm trying to pass variables to a command line program by feeding a string into subprocess, but here's simple example to reproduce the error:
import subprocess
path = '/home/user/Desktop/directory(2018)'
command_str = 'rmdir ' + path
print (subprocess.run(command_str))
which gives me this error:
Traceback (most recent call last):
File "ex.py", line 7, in <module>
print (subprocess.run(command_str))
File "/usr/lib/python3.6/subprocess.py", line 403, in run
with Popen(*popenargs, **kwargs) as process:
File "/usr/lib/python3.6/subprocess.py", line 709, in __init__
restore_signals, start_new_session)
File "/usr/lib/python3.6/subprocess.py", line 1344, in _execute_child
raise child_exception_type(errno_num, err_msg, err_filename)
FileNotFoundError: [Errno 2] No such file or directory: 'rmdir /home/user/Desktop/directory(2018)': 'rmdir /home/user/Desktop/directory(2018)'
When I write it directly into the terminal with escape characters it works great.
$ rmdir /home/user/Desktop/directory\(2018\)
But in Python when I try to add escape characters to the strings before calling subprocess:
command_str = command_str.replace('(','\(')
command_str = command_str.replace(')','\)')
I get the same error as before because, unlike print, the subprocess string adds a second escape character which gets passed to the terminal.
Traceback (most recent call last):
File "ex.py", line 7, in <module>
print (subprocess.run(command_str))
File "/usr/lib/python3.6/subprocess.py", line 403, in run
with Popen(*popenargs, **kwargs) as process:
File "/usr/lib/python3.6/subprocess.py", line 709, in __init__
restore_signals, start_new_session)
File "/usr/lib/python3.6/subprocess.py", line 1344, in _execute_child
raise child_exception_type(errno_num, err_msg, err_filename)
FileNotFoundError: [Errno 2] No such file or directory: 'rmdir /home/user/Desktop/directory\\(2018\\)': 'rmdir /home/user/Desktop/directory\\(2018\\)'
Is there a way to fix this particular error? Either by doing something different with replace or subprocess.run? (I'm not looking for a better way to remove directories.) Thanks.
Python implements rm and rmdir so no need to call a process. In general, if you want to skip shell processing on a command in subprocess, don't use the shell.
import subprocess
path = '/home/user/Desktop/directory(2018)'
command = ['rmdir', path]
print (subprocess.run(command, shell=False))
The shell breaks a command line into a list of arguments. You can build that list yourself and skip the shell completely.
Do not use subprocess, and you don't have to worry about shell escaping. Use the high-level file operation APIs provided in stdlib's shutil:
import shutil
shutil.rmtree('/home/user/Desktop/directory(2018)')

Python subprocess call throws error when writing file

I'd like to use SVOX/pico2wave to write a wav-file from Python code. When I execute this line from a terminal the file is written just fine:
/usr/bin/pico2wave -w=/tmp/tmp_say.wav "Hello world."
I've verified that pico2wave is located in /usr/bin.
This is my Python code:
from subprocess import call
call('/usr/bin/pico2wave -w=/tmp/tmp_say.wav "Hello world."')
... which throws this error:
Traceback (most recent call last):
File "app/app.py", line 63, in <module>
call('/usr/bin/pico2wave -w=/tmp/tmp_say.wav "Hello world."')
File "/usr/lib/python2.7/subprocess.py", line 168, in call
return Popen(*popenargs, **kwargs).wait()
File "/usr/lib/python2.7/subprocess.py", line 390, in __init__
errread, errwrite)
File "/usr/lib/python2.7/subprocess.py", line 1024, in _execute_child
raise child_exception
OSError: [Errno 2] No such file or directory
From the documentation
Providing a sequence of arguments is generally preferred, as it allows
the module to take care of any required escaping and quoting of
arguments (e.g. to permit spaces in file names). 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.
So you might try with
call(['/usr/bin/pico2wave', '-w=/tmp/tmp_say.wav', '"Hello world."'])

subprocess error message:[Errno 2] in _execute_child raise child_exception

In my program I call the command:
command_two = 'sfit4Layer0.py -bv5 -fs'
subprocess.call(command_two.split(), shell=False)
I am using PyCharm and I get the error message:
Traceback (most recent call last):
File "part2test.py", line 5, in <module>
subprocess.call(command_two.split(), shell=False) #writes the summary file
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/subprocess.py", line 522, in call
return Popen(*popenargs, **kwargs).wait()
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/subprocess.py", line 710, in __init__
errread, errwrite)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/subprocess.py", line 1335, in _execute_child
raise child_exception
OSError: [Errno 2] No such file or directory
When walking through my program, it never gets to the program I want it to sfit4Layer0.py, it is getting stuck in subprocess but I am not sure why. Changing the shell=True doesn't do anything helpful either - I don't get these error messages but it does not execute my code properly. Any suggestions would be helpful.
My bash profile:
PATH="~/bin:/usr/bin:${PATH}"
export PATH PYTHONPATH="/Users/nataliekille/Documents/sfit4/pbin/Layer0:/Users/nataliekille/Documents/sfit4/pbin/Layer1:/Users/nataliekille/Documents/sfit4/pbin/ModLib:/Users/nataliekille/Documents/sfit4/SpectralDB"
export PYTHONPATH
PATH=${PATH}:${PYTHONPATH}
export PATH
You've missed an important part of the subprocess documentation. "If passing a single string [at the command, rather than a list of strings], either shell must be True (see below) or else the string must simply name the program to be executed without specifying any arguments."
So the kernel is compaining because there is not executable with the name 'sfit4Layer0.py -bv5 -fs'. Should work if you replace the string with (for example) 'sfit4Layer0.py -bv5 -fs'.split(), or ['sfit4Layer0.py', '-bv5', '-fs'].

"OSError: [Errno 2] No such file or directory" while using python subprocess with command and arguments

I am trying to run a program to make some system calls inside Python code using subprocess.call() which throws the following error:
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/usr/lib/python2.7/subprocess.py", line 493, in call
return Popen(*popenargs, **kwargs).wait()
File "/usr/lib/python2.7/subprocess.py", line 679, in __init__
errread, errwrite)
File "/usr/lib/python2.7/subprocess.py", line 1249, in _execute_child
raise child_exception
OSError: [Errno 2] No such file or directory
My actual Python code is as follows:
url = "/media/videos/3cf02324-43e5-4996-bbdf-6377df448ae4.mp4"
real_path = "/home/chanceapp/webapps/chanceapp/chanceapp"+url
fake_crop_path = "/home/chanceapp/webapps/chanceapp/chanceapp/fake1"+url
fake_rotate_path = "/home/chanceapp/webapps/chanceapp.chanceapp/fake2"+url
crop = "ffmpeg -i %s -vf "%(real_path)+"crop=400:400:0:0 "+ "-strict -2 %s"%(fake_crop_path)
rotate = "ffmpeg -i %s -vf "%(fake_crop_path)+"transpose=1 "+"%s"%(fake_rotate_path)
move_rotated = "mv"+" %s"%(fake_rotate_path)+" %s"%(real_path)
delete_cropped = "rm "+"%s"%(fake_crop_path)
#system calls:
subprocess.call(crop)
Can I get some relevant advice on how to solve this?
Use shell=True if you're passing a string to subprocess.call.
From docs:
If passing a single string, either shell must be True or
else the string must simply name the program to be executed without
specifying any arguments.
subprocess.call(crop, shell=True)
or:
import shlex
subprocess.call(shlex.split(crop))
No such file or directory can be also raised if you are trying to put a file argument to Popen with double-quotes.
For example:
call_args = ['mv', '"path/to/file with spaces.txt"', 'somewhere']
In this case, you need to remove double-quotes.
call_args = ['mv', 'path/to/file with spaces.txt', 'somewhere']
Can't upvote so I'll repost #jfs comment cause I think it should be more visible.
#AnneTheAgile: shell=True is not required. Moreover you should not use
it unless it is necessary (see # valid's comment). You should pass
each command-line argument as a separate list item instead e.g., use
['command', 'arg 1', 'arg 2'] instead of "command 'arg 1' 'arg 2'". –
jfs Mar 3 '15 at 10:02

python subprocess call OSX

I am trying to access the wifi interface through python:
In bash I can use the following
/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport /usr/sbin/airport -I
-s can also be passed.
I have tried using the following in python:
from subprocess import call
call(['/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport /usr/sbin/airport', '-I'])
something is definitely not correct - as I get as a reply:
Traceback (most recent call last):
File "ip3.py", line 5, in <module>
call(['/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport /usr/sbin/airport', '-I'])
File "/Library/Frameworks/Python.framework/Versions/3.2/lib/python3.2/subprocess.py", line 467, in call
return Popen(*popenargs, **kwargs).wait()
File "/Library/Frameworks/Python.framework/Versions/3.2/lib/python3.2/subprocess.py", line 741, in __init__
restore_signals, start_new_session)
File "/Library/Frameworks/Python.framework/Versions/3.2/lib/python3.2/subprocess.py", line 1356, in _execute_child
raise child_exception_type(errno_num, err_msg)
OSError: [Errno 2] No such file or directory: '/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport /usr/sbin/airport'
Any ideas would be welcome... I just want to begin by printing this to screen, saving as an array etc...
I dont have a high enough rating to answer my own question yet, so Ill say it here!
so I was being stupid!
from subprocess import call
call(['/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport', '-I'])
Works fine. Just needed to remove /usr/sbin/airport
call take first argument as command and subsequent arguments to that command.
In your case
command is,
/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport
and command's two arguments are,
/usr/sbin/airport
-I
So, you need to call it as,
from subprocess import call
call(['/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport' '/usr/sbin/airport', '-I'])
Try like this
from subprocess import call
call(['/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport', '/usr/sbin/airport', '-I'])
Otherwise it thinks /usr/sbin/airport is part of the first path.

Categories