Command program not executing from PYTHON subprocess - python

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.

Related

Running Command from Python. Works with os.system but not subprocces.run

I have been on this problem for quite a while now. I have this command line that I want run trough python:
Users\name.lastname\Desktop\TESTER\Latitude 5431\Latitude-5431-46KCM_Win10_1.0_A01.exe /s /e=C:Users\name.lastname\Desktop\TESTER\Latitude 5431
this should run the .exe and then extract the files to the specified folder. I tried this with os.system and it worked but when I run it with
import subprocess
x = '"' + "\\Users\\name.lastname\\Desktop\\TESTER\\Latitude 5431\\Latitude-5431-46KCM_Win10_1.0_A01.exe" + '" ' + "/s /e=C:Users\\name.lastname\\Desktop\\TESTER\\Latitude 5431"
p1 = subprocess.run(x, shell=True)
it only shows me 'tips' like these but no error message and the .exe is not executed.
Pass command line arguments directly to vendor installer.
Turn the return code to success if required
Latitude-5431-46KCM_Win10_1.0_A01.exe /factoryinstall /passthrough D:\Sample.xml C:\log\FI.log
Change from the default log location to C:\my path with spaces\log.txt
Latitude-5431-46KCM_Win10_1.0_A01.exe /l="C:\my path with spaces\log.txt"
Force update to continue, even on "soft" qualification errors
Latitude-5431-46KCM_Win10_1.0_A01.exe /s /f
Try running without shell=True as it makes things more complicated than it helps:
import subprocess
prog = r"C:\Users\name.lastname\Desktop\TESTER\Latitude 5431\Latitude-5431-46KCM_Win10_1.0_A01.exe"
args = ["/s", r"/e=C:\Users\name.lastname\Desktop\TESTER\Latitude 5431"]
subprocess.run([prog]+args)

Subprocess does not execute exiftool command

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.

Unexpected behaviour when calling shell command on a deployed web app

I am deploying a flask app, in which a multiprocessing.Process will be started. Inside this process I call a shell command trough subprocess.call(). The script runs fine when executed on local host, when deployed with nginx and gunicorn, the flask app behaves as expected until the subprocess starts, then I recieve the following error log:
DEBUG:root:start to run command
DEBUG:root:(<class 'FileNotFoundError'>, FileNotFoundError(2, "No such file or directory: 'java -jar ábsolute/path/to/jar/file')
Process(
target=decode_upload,
args=(
path_to_blf,
path_to_dbc_folder,
path_to_splitted,
path_to_decoder,
system_layout,
dc_doc,
dc_id,
file_type,
)
).start()
Here is the rellevant part of the function.
def decode_file(
path_to_blf,
path_to_dbc_folder,
path_to_splitted,
path_to_decoder,
system_layout=DEFAULT_SYSTEM_LAYOUT):
command = "{} {} --blf={}".format(
SOFTWARE_COMMAND,
path_to_decoder,
path_to_blf
)
for dbc_file_name in DBC_FILE_NAME_LIST:
command += " --dbc={}".format(
os.path.join(
path_to_dbc_folder,
dbc_file_name
)
)
command += " --out={}".format(path_to_splitted)
logging.debug("start to run command")
subprocess.call(command)
logging.debug(f)
logging.debug("run command end")
def decode_upload(
path_to_blf,
path_to_dbc_folder,
path_to_splitted,
path_to_decoder,
system_layout,
dc_doc,
dc_id,
file_type):
logging.basicConfig(filename='flask.log',level=logging.DEBUG)
logging.debug('This message should go to the log file')
try:
decode_file(
path_to_blf,
path_to_dbc_folder,
path_to_splitted,
path_to_decoder,
system_layout)
except:
logging.debug(sys.exc_info())
The process fails when it gets to this line.
subprocess.call(command)
if I try to call the "command" from the command line it works without a problem.
from subprocess import Popen
command='your complete command as you paste on cmd'
p1=Popen(command,Shell=True)
This will help you to run the command as complete string
The proper solution is to pass the command as a list of parsed arguments. You need to understand how the shell handles quoting and argument splitting to do this right.
As a quick cheat,
printf "'%s'\n" your command line here
in your shell should give you a good idea of how the shell expands the arguments. For example
bash$ printf "'%s'\n" java -jar "/path/complex path with spaces.jar" \* \>\<
'java'
'-jar'
'/path/complex path with spaces.jar'
'*'
'><'
shows you that you need
subprocess.call(['java', '-jar', '/path/complex path with spaces.jar', '*', '><'])
Adapting your code for this, we obtain
command = [SOFTWARE_COMMAND, path_to_decoder, '--blf={}'.format(path_to_blf)]
for dbc_file_name in DBC_FILE_NAME_LIST:
command.append("--dbc={}".format(
os.path.join(path_to_dbc_folder, dbc_file_name)))
command.append("--out={}".format(path_to_splitted))

Executing DevCon CMD command from python

I want to restart driver with DevCon from python script. It works from command line with this command:
devcon restart \"sd0007322081041363_kcanv\"
I tried this:
os.system("devcon restart \"sd0007322081041363_kcanv\"")
with result:
'devcon' is not recognized as an internal or external command
I read that os.system is obsolete and i need to use subprocess.check_output so i try this:
subprocess.check_output(['devcon', 'restart', '"sd0007322081041363_kcanv"'])
with result:
WindowsError:[Error 2] The system cannot find the file specified
and this:
subprocess.check_output('devcon restart "sd0007322081041363_kcanv"', shell=True)
with result:
subprocess.CalledProcessError: Command 'devcon restart "sd0007322081041363_kcanv"' returned non-zero exit status 1
and this:
subprocess.Popen("devcon restart \"sd0007322081041363_kcanv\"", shell=True, stdout=subprocess.PIPE).stdout.read()
result:
'devcon' is not recognized as an internal or external command
and this:
try:
subprocess.check_output('devcon disable "sd0007322081041363_kcanv" /f',shell=True,stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as e:
raise RuntimeError("command '{}' return with error (code {}): {}".format(e.cmd, e.returncode, e.output))
with result:
RuntimeError: command 'devcon disable "sd0007322081041363_kcanv" /f' return with errpr (cpde 1): 'devcon' is not recognized as an internal or external command, operable program or batch file
devcon.exe is under Windows/System32 and it is set in system path.
I know that this can be duplicate question but I have tried many solution on stackoverflow but i van't resolve this issue.
Finally, I came up with a solution. I tried many things but this is what works for me:
copy devcon.exe from C:\Windows\System32 and put it to C:\Windows\SysWOW64.
my code:
try:
subprocess.check_output('C:\\Windows\\SysWOW64\\devcon.exe restart "sd0007322081041363_kcanv" /f',shell=True,stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as e:
raise RuntimeError("command '{}' return with error (code {}): {}".format(e.cmd, e.returncode, e.output))

commands.getstatusoutput fails saying sh: Syntax error: ";" unexpected

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.

Categories