I try to use Python envoy for better access to Shell programs. But i have a problem that i want to delete all items of a folder, but envoy can't handle my varaible:
import envoy
import os
# Check for a empty folder.
if len(os.listdir(csv_save_path)) != 0:
for item in os.listdir(csv_save_path):
result = envoy.run('rm -v',item)
print result.std_out
print result.std_err
Output:
"rm: missing operand\nTry `rm --help' for more information.\n"
I don't want use subprocces. Anyone a idea what is wrong?
Edit:
Thank for your quick response. Now i get this error message:
Exception in thread Thread-4:
Traceback (most recent call last):
File "/usr/lib64/python2.7/threading.py", line 552, in __bootstrap_inner
self.run()
File "/usr/lib64/python2.7/threading.py", line 505, in run
self.__target(*self.__args, **self.__kwargs)
File "/usr/lib64/python2.7/site-packages/envoy/core.py", line 40, in target
bufsize=0,
File "/usr/lib64/python2.7/subprocess.py", line 679, in __init__
errread, errwrite)
File "/usr/lib64/python2.7/subprocess.py", line 1228, in _execute_child
raise child_exception
OSError: [Errno 2] No such file or directory
*** AttributeError: 'NoneType' object has no attribute 'returncode'
But i check on the path of the file, with and without path, it's failing.
Edit: The Solution is to use %s to get the item to the right place.
import envoy
import os
# Check for a empty folder.
if len(os.listdir(csv_save_path)) != 0:
for item in os.listdir(csv_save_path):
result = envoy.run('rm -v %s' % item)
print result.std_out
print result.std_err
so far
The second parameter of envoy.run is a timeout. You want:
# The check for the empty folder is superfluous
for item in os.listdir(csv_save_path):
filepath = os.path.join(csv_save_path, item)
result = envoy.run(['rm', '-v', '--', filepath])
print (result.std_out)
print (result.std_err)
By the way, why are you using the command-line rm instead of Python's os.unlink?
Try this
import envoy
import os
# Check for an empty folder.
if len(os.listdir(csv_save_path)) != 0:
for item in os.listdir(csv_save_path):
result = envoy.run('rm -v %s' % item)
print "Output: %s" % result.std_out
print "Error: %s" % result.std_err
You can also use shlex.split to help you form the list to supply to envoy.run() instead of crafting/coding the list by hand.
E.g.
>>> from shlex import split
>>> split("rm -v -- filename")
['rm', '-v', '--', 'filename']
In your case, the code would look like this:
from shlex import split
# ......
result = envoy.run(split('rm -v %s' % (item)))
Related
I want to add ffmpeg options to a variable and later use it in a subprocess call. If the variable contains one word, all is well, but if it contains more than one, I get errors. I am working on a larger script and I will need to have extra options such as this for certain codecs. How can I get this working?
The following works perfectly for me:
import subprocess
import sys
video_codec = 'libx264'
output = sys.argv[1] + '.mkv'
subprocess.call(['ffmpeg',
'-i',sys.argv[1],
'-c:v',video_codec,
'-c:a','copy',
output])
Once I introduce new options/spaces to video_options as such:
video_codec = "'libx264', '-pix_fmt', 'yuv420p'"
I get an ffmpeg error:
Unknown encoder ''libx264', '-pix_fmt', 'yuv420p''
If I remove the double quotes and just use
video_codec = 'libx264', '-pix_fmt', 'yuv420p'
I get a python error:
Traceback (most recent call last):
File "testo.py", line 10, in <module>
output])
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/subprocess.py", line 524, in call
return Popen(*popenargs, **kwargs).wait()
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/subprocess.py", line 711, in __init__
errread, errwrite)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/subprocess.py", line 1308, in _execute_child
raise child_exception
TypeError: execv() arg 2 must contain only strings
Eric Renouf has it right, but don't create a string, its less reliable. You just have to break apart your config like this:
video_codecs = ['libx264', '-pix_fmt', 'yuv420p']
output = sys.argv[1] + '.mkv'
cmd_list = ['ffmpeg',
'-i',sys.argv[1],
'-c:v']
cmd_list += video_codecs
cmd_list += ['-c:a','copy',
output]
subprocess.call(cmd_list)
I'm not sure if the order matters, so I preserved it here, if order doesn't matter, you can just combine the last line with the third line.
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
So, I have a simple class where I am trying to save a string response from a terminal ffmpeg command into an object property:
import os
import subprocess
class Movie(object):
absolute_path = None
movie_info = None
def __init__(self, path):
self.absolute_path = "%s/%s" % (os.getcwd(), path)
if(os.path.exists(self.absolute_path) is False):
raise IOError("File does not exist")
def get_movie_info(self):
ffmpeg_command = "ffmpeg -i %s" % self.absolute_path
self.movie_info = subprocess.call(ffmpeg_command)
print self.movie_info
When I then run this command in cmd:
import os
import sys
sys.path.append(os.getcwd())
from Encode.Movie import Movie
try:
movie = Movie("tests/test_1.mpg")
movie.get_movie_info()
except IOError as e:
print e
I get this exception:
richard#richard-desktop:~/projects/hello-python$ python main.py
Traceback (most recent call last):
File "main.py", line 9, in <module>
movie.get_movie_info()
File "/home/richard/projects/hello-python/Encode/Movie.py", line 16, in get_movie_info
self.movie_info = subprocess.call(ffmpeg_command)
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
The path is correct because when I do print self.absolute_path before subprocess.call(), I get:
/home/richard/projects/hello-python/tests/test_1.mpg
And this file exists.
The problem is
ffmpeg_command = "ffmpeg -i %s" % self.absolute_path
self.movie_info = subprocess.call(ffmpeg_command)
you give a single string as command line, but you omit the parameter shell=True.
The recommended way is, however, to do
ffmpeg_command = ["ffmpeg", "-i", self.absolute_path]
self.movie_info = subprocess.call(ffmpeg_command)
in order to give the command and arguments separately. This way, you have no problems with quoting etc, and you omit an unnecessary shell call.
BTW, If you want to store the output of a command in a variable, then you should use check_output instead of a call
http://docs.python.org/library/subprocess.html#subprocess.check_output
I actually used this way of getting the output from ffmpeg as it is an error output:
ffmpeg_command = ["avconv", "-i", self.absolute_path]
p = Popen(ffmpeg_command, stdout=PIPE, stderr=PIPE)
stdout, stderr = p.communicate()
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?
So I have a python script that generates a file name based on the time. Then I am trying to cat some data into that file name. However, it seems that I cannot pass it in or something.
Here is what the code looks like:
fileName = "parsedOn_"+strftime("%Y_%m_%d_%H%M%S", gmtime())+".csv"
subprocess.call(['cat' + 'xaa' + '>' + fileName])
Here is the error I get:
Traceback (most recent call last):
File "parseCSV.py", line 96, in <module>
subprocess.call(['cat' + 'xaa' + '>' + finalFile1])
File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/subprocess.py", line 444, in call
return Popen(*popenargs, **kwargs).wait()
File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/subprocess.py", line 595, in __init__
errread, errwrite)
File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/subprocess.py", line 1106, in _execute_child
raise child_exception
OSError: [Errno 2] No such file or directory
Any ideas if what I'm trying to do is possible with subprocess at all?
The problem lies in
subprocess.call(['cat' + 'xaa' + '>' + fileName])
First of all, you're missing spaces (if you wanted to use a string), or commas (if you wanted to use a list, the preferred method). Secondly, > is a shell redirection, so you must execute this line in a shell, as in:
subprocess.call('cat xaa > ' + fileName, shell=True)
But you should not do that. Instead, use Python's native shutil.copyfile:
shutil.copyfile('xaa', fileName)
You should consider using envoy.
Sample
In [1]: import envoy
In [2]: r = envoy.run("cat requirements.txt")
In [3]: r.std_out
Out[3]: 'Flask==0.8\ngit+git://github.com/kennethreitz/flask-cache.git\nJinja2==2.6\ngit+git://github.com/kennethreitz/werkze ug.git\ndistribute==0.6.24\ngunicorn==0.13.4\nredis==2.4.9\nvanity==1.1.1\nwsgiref==0.1.2\n'
In [4]: print r.std_out
Flask==0.8
git+git://github.com/kennethreitz/flask-cache.git
Jinja2==2.6
git+git://github.com/kennethreitz/werkzeug.git
distribute==0.6.24
gunicorn==0.13.4
redis==2.4.9
vanity==1.1.1
wsgiref==0.1.2
Edit:
Main advantage of envoy is simplicity.