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()
Related
I am trying to read input from the user and store it in a variable by using subprocess.check_output in python2.7. But it shows up the error OSError: [Errno 2] No such file or directory when I try to run it. Also it is to be noted that I strictly want to use shell=False because of the security concerns.
I have tried subprocess.Popen and it doesnt work that way too.
I have tried to use sys.stdin = open('/dev/tty', 'r') and stdin=subprocess.PIPE but give the same error as above.
>>> import sys
>>> import subprocess
>>> sys.stdin = open('/dev/tty', 'r')
>>> cmd = ('read userinput && echo "$userinput"')
>>> confirmation = subprocess.check_output(cmd.split(), stdin=sys.stdin).rstrip()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python2.7/subprocess.py", line 567, in check_output
process = Popen(stdout=PIPE, *popenargs, **kwargs)
File "/usr/lib/python2.7/subprocess.py", line 711, in __init__
errread, errwrite)
File "/usr/lib/python2.7/subprocess.py", line 1343, in _execute_child
raise child_exception
OSError: [Errno 2] No such file or directory
The expected result is that it should ask for user input and store it to the confirmation variable
You are entering a shell command (read and echo are shell built-ins, and && is shell syntax), therefore you need shell=True. This is a single shell command, so you don't use the split. The parentheses around the command in python have no effect in this case:
import sys
import subprocess
sys.stdin = open('/dev/tty', 'r')
cmd = 'read userinput && echo "$userinput"'
confirmation = subprocess.check_output(cmd, stdin=sys.stdin, shell=True).rstrip()
print'****', confirmation
Gives:
$ python gash.py
hello
**** hello
I have to print bash history using subprocess package.
import subprocess
co = subprocess.Popen(['history'], stdout = subprocess.PIPE)
History = co.stdout.read()
print("----------History----------" + "\n" + History)
but they prompt an error
Traceback (most recent call last):
File "test.py", line 4, in <module>
co = subprocess.Popen(['history'], stdout = subprocess.PIPE)
File "/usr/lib/python2.7/subprocess.py", line 394, in __init__
errread, errwrite)
File "/usr/lib/python2.7/subprocess.py", line 1047, in _execute_child
raise child_exception
OSError: [Errno 2] No such file or directory
Normally, you would need to add shell=True argument to your Popen call:
co = subprocess.Popen(['history'], shell=True, stdout = subprocess.PIPE)
Or to manually specify the shell you want to call.
co = subprocess.Popen(['/bin/bash', '-c', 'history'], stdout = subprocess.PIPE)
Unfortunately, in this particular case it won't help, because bash has empty history when used non-interactively.
A working solution would be to read ${HOME}/.bash_history manually.
Kit is correct, reading ~/.bash_history may be a better option:
from os.path import join, expanduser
with open(join(expanduser('~'), '.bash_history'), 'r') as f:
for line in f:
print(line)
I am try to execute below command using python subprocess but it is failing.
Please help
import subprocess
cmd = "bash /opt/health_check -t 2>/dev/null"
retcode = subprocess.call([cmd])
print retcode
I am getting below output:
Traceback (most recent call last):
File "./script.py", line 65, in <module>
retcode = subprocess.call([cmd])
File "/usr/lib64/python2.7/subprocess.py", line 522, in call
return Popen(*popenargs, **kwargs).wait()
File "/usr/lib64/python2.7/subprocess.py", line 710, in __init__
errread, errwrite)
File "/usr/lib64/python2.7/subprocess.py", line 1335, in _execute_child
raise child_exception
OSError: [Errno 2] No such file or directory
If you call check_output with a list, you would need to tokenize the command yourself, as in:
import subprocess
cmd = ["bash", "/opt/health_check", "-t"]
retcode = subprocess.call([cmd])
print retcode
This doesn't use a shell so you can't use input redirection. If you really want to execute your command with a shell, then pass a string and set shell=True:
import subprocess
cmd = "bash /opt/health_check -t 2>/dev/null"
retcode = subprocess.call(cmd, shell=True)
print retcode
This is an incorrect way to call subprocess. A quick and dirty way to do it is to change it like:
subprocess.call(cmd, shell=True)
This will invoke the system's shell to execute the command, and you'll have access to all the goodies it provides. It's not something to use ligthly, however, so check security considerations from the docs before doing so.
Otherwise, you can simply provide the command as a list, like so:
subprocess.call(["bash", "/opt/health_check"])
I'm having issues with Python finding an available Executable on my Linux machine. My default PATH includes this Executable (svnlook) but when I run the python script the below function fails to find executable. Any ideas on how to fix this?
def command_output(cmd):
child = subprocess.Popen(cmd.split(), stdout=subprocess.PIPE)
output = child.communicate()[0]
return output, child.returncode
def get_author():
cmd = "svnlook author %s %s %s" % (svn_opt, svn_txn, svn_repo)
author, return_code = command_output(cmd)
return author.strip()
Error:
Traceback (most recent call last):
File "/home/user/app/csvn/data/repositories/repo/hooks/pre-commit", line 82, in <module>
author = get_author()
File "/home/user/app/csvn/data/repositories/repo/hooks/pre-commit", line 53, in get_author
author, return_code = command_output(cmd)
File "/home/user/app/csvn/data/repositories/repo/hooks/pre-commit", line 36, in command_output
child = subprocess.Popen(cmd.split(), stdout=subprocess.PIPE)
File "/home/user/app/activepython-2.7.2.5_x86_64/lib/python2.7/subprocess.py", line 679, in __init__
errread, errwrite)
File "/home/user/app/activepython-2.7.2.5_x86_64/lib/python2.7/subprocess.py", line 1228, in _execute_child
raise child_exception
OSError: [Errno 2] No such file or directory
Error: [Errno 2] No such file or directory
You probably want to provide the full path to the executable, e.g. /usr/bin/svnlook or /usr/local/bin/svnlook instead of just svnlook.
See this answer to a related question for details.
Try running it from the console. Make sure the permissions/executability is correct. Try os.system().
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)))