I am running mongoimport command using python commands module as
status = utilities.execute(mongoimport)
in utilities.py
def execute(command):
if not command:
return (-1, 'command can not be empty or null')
return commands.getstatusoutput(command)
When I run this, I see error as
sh: Syntax error: ";" unexpected
I see that documentation says :
commands.getstatusoutput(cmd)
Execute the string cmd in a shell with os.popen() and return a 2-tuple (status, output). cmd is actually run as { cmd ; } 2>&1, so that the returned output will contain output or error messages
How can I fix this to be able to run this command?
Use the subprocess module
from subprocess import check_output
output = check_output(["ls", "-l"])
This will raise an error if the command fails - no need to check for empty string. If you are really sure that you want to pass stuff through the shell then call like this
output = check_output("ls -l", shell=True)
Just note that passing stuff through the shell is an excellent vector for security problems.
Related
Iam trying to execute an exif command using subprocess. The command is :
['exiftool', '-ID3:Picture', '-b', '-ThumbnailImage', '/home/mediaworker/Downloads/Raabta.mp3', '>', '/mnt/share_PROXY/exifData/Raabta.jpg']
Now, the issue is that it returns the status code as 1. But if i execute the same command in the terminal, it executes successfully. The file is written to the location. Is my command going wrong in subprocess ? The error i get when i run my python script is :
Error: File not found - >
Error: File not found - /mnt/share_PROXY/exifData/Raabta.jpg
The code implementation is as follows:
file_name = os.path.basename(file_loc)
file_name = file_name.replace(os.path.splitext(file_name)[1], ".jpg")
dst_loc = os.path.join(dst_loc, file_name)
cmd_ = ["exiftool", "-ID3:Picture", "-b", "-ThumbnailImage", file_loc, ">", dst_loc]
logger.info("Command is {}".format(cmd_))
try:
p = subprocess.Popen(cmd_, stdout=subprocess.PIPE)
p.communicate()
if p.returncode != 0:
logger.error("Failed to write thumbnail artwork")
else:
id3_metadata.append({"file_thumbnail_info_path": dst_loc})
except Exception:
logger.error("[extract_iptc_metadata] Exception : '{}'".format(ex))
The error output refers to the redirection >.
The proper way to redirect using subprocess is using the stdout parameter.
with open(dst_loc, 'wb') as f:
p = subprocess.Popen(cmd_, stdout=f)
p.communicate()
The '>', '/mnt/share_PROXY/exifData/Raabta.jpg' part of your command is shell redirection and is a function of the command line/shell. It is not available when you execute a command from python in this way.
The option you want to look at is the -W (-tagOut) option. This would be the example command you want to work off of. Just replace -preview:all with the tag you want to extract, which would be -ThumbnailImage in this case.
How to call the following command using subprocess in python " python -m xport C:/abc.xpt > C:/abc.csv "?
The command works properly in command prompt.
But gives an error when tried to execute via subprocess in python.
subprocess.call(["python", "-m", "xport", "C:/abc.xpt" , ">" , "C:/abc.csv"])
The above command gives an error saying,
usage: xport.py [-h] [input]
xport.py: error: unrecognized arguments: C:/abc.csv
> C:/abc.csv is a redirect of the output to a text file and not part of the command.
But if you are inside a python script already, why don't you call the function or module directly? There is no need to use a subprocess, but if you want to use it you need to catch the output and store it somewhere (in a variable or file)
>>> proc = subprocess.Popen('ls', stdout=subprocess.PIPE)
>>> output = proc.stdout.read()
>>> print output
bar
baz
foo
I am in a process of building a simple remote shell tool to communicate with Windows 10. Server sends a "message" through its own shell to the client who runs the message. I need this received message to be run by other process other that default cmd (shell=True) - a specified app.exe. Here is the code that runs on the client:
1)
def work( storage, message ) :
import subprocess
process = subprocess.Popen([message], stdout=subprocess.PIPE, stderr=None, shell=True)
#Launch the shell command:
output = process.communicate()
print output[0]
I tried including "app.exe" or "cmd" to execute the message but with that I get error: TypeError: bufsize must be an integer.
I have also tried pinpointing the issue locally and I can run:
2)
import subprocess
import sys
subprocess.Popen(["C:\\Users\\User\\Desktop\\app.exe", "-switch"] + sys.argv[1:], shell=False)
and pass arguments from a command terminal and it works as it should. Now I am trying to apply the same logic to a remote execution with my program and use either solution 1 or 2.
Update:
3) Trying to implement what I did locally to a remote solution:
def work( storage, message ) :
import subprocess
import sys
process = subprocess.Popen(["C:\\Users\\User\\Desktop\\app.exe", "-switch"] + sys.argv[1:], shell=False)
#Launch the shell command:
output = process.communicate()
print output[0]
I tried replacing sys.argv[1:] with message but I get:
TypeError: can only concatenate list (not "str") to list
shell=True doesn't mean the first argument to Popen is a list of arguments to the shell; it just means the first argument is processed by the shell, rather than being arguments to whatever system call your system would use to execute a new process.
In this case, you appear to want to run app.exe with a given argument; that's simply
cmd = r"C:\Users\User\Desktop\app.exe"
subprocess.Popen([cmd, "-switch", message], stdout=subprocess.PIPE)
#chepner sir, you are a very helpful. That was it! I am so happy, thanks for your help.
Your solution:
Popen(["...\\app.exe", "-switch", message], stdout=subprocess.PIPE, stderr=None)
That was the badger!
I am invoking shell script using os.execvp() in python. my shell script has some echo statements whcih I want to redirect in file.
Here is what I am trying:
cmd = "/opt/rpm/rpm_upgrade.sh >& /opt/rpm/upgrader.log"
cmdline = ["/bin/sh", cmd]
os.execvp(cmdline[0], cmdline)
Below is the error I am getting:
Error: /bin/sh: /opt/rpm/rpm_upgrade.sh >& /opt/rpm/upgrader.log: No such file or directory
Can any one help?
This is happening because you are passing this entire string as if it were the program name to execute:
"/opt/rpm/rpm_upgrade.sh >& /opt/rpm/upgrader.log"
The easy way to fix this is:
cmdline = ["/bin/sh", "/opt/rpm/rpm_upgrade.sh",
">&", "/opt/rpm/upgrader.log"]
os.execvp(cmdline[0], cmdline)
Now sh will receive three arguments rather than one.
Or you can switch to the more full-featured subprocess module, which lets you redirect output in Python:
import subprocess
with open("/opt/rpm/upgrader.log", "wb") as outfile:
subprocess.check_call(["/opt/rpm/rpm_upgrade.sh"], shell=True,
stdout=outfile, stderr=subprocess.STDOUT)
I downloaded a python program (PYPDFOCR) that runs through the command line. PYPDFOCR has several dependencies (ghost script, image magick, etc..)
When I execute the program in the command line, it fails. The code executes GhostScript with all its arguments but I get the error that the command is not recognized.
If I go to the command line, I can execute ghost script "C:\Programs.....\gswin64c.exe" and pass the arguments and get the result. However, when I run PYPDFOCR, it fails everytime.
def _run_gs(self, options, output_filename, pdf_filename):
try:
cmd = '%s -q -dNOPAUSE %s -sOutputFile="%s" "%s" -c quit' % (self.binary, options, output_filename, pdf_filename)
logging.info(cmd)
out = subprocess.check_output(cmd, shell=True)
except subprocess.CalledProcessError as e:
print e.output
if "undefined in .getdeviceparams" in e.output:
error(self.msgs['GS_OUTDATED'])
else:
error (self.msgs['GS_FAILED'])
The error I get in the command is "C\Program" is not recognized as an internal or external command, operable program or batch file.
When I print the contents of the command, it shows:
c:\Program File\gs\gs9.16\bin\gswin64c.exe" -q -dNOPAUSE -sDEVICE=j[ecgray -dJPEG=75 -r300 -sOutputFILE="C:\test\a3_%d.jpg "c:\test\a3.pdf" -c quit
Again, I can run the c:...gswin64.exe command without the program.
Any help will be deeply appreciated.
The problem is probably that the space after Program in 'Program Files' is not correctly escaped. Use some function like
def shellquote(s):
return "'" + s.replace("'", "'\\''") + "'"
to escape your command before starting the process.
(Example function taken from here)
I had the same problem on Windows with windres.
It turned out to be a windres problem (MinGW64 4.8.3.20141208 from chocolatey).
I debugged into it and found that subprocess.Popen(cmd,**kw),
cmd being a list with first entry the executable's path,
mapped to _winapi.CreateProcess(executable, cmd, ...), with executable=None.
So the error originated from winapi.
In the Posix branch in subprocess there is
if executable is None:
executable = args[0]
which is missing in the windows branch.
As a try I setexecutable in **kw: Still the same problem.
Then I found https://amindlost.wordpress.com/2012/06/09/mingw-windres-exe-cant-popen-error/.
Indeed it worked with msys2's ming64's windres.