Python subprocess issue with ampersands - python

I'm currently having a major issue with a python script. The script runs arbitrary commands through a handler to convert incorrect error reporting into correct error reporting.
The issue I'm having is getting the script to work correctly on windows with a command that contains ampersands in it's path. I've attempted quoting the command, escaping the ampersand with ^ and neither works. I'm now out of ideas. Any suggestions?
To clarify from current responses:
I am using the subprocess module
I am passing the command line + arguments in as a list
The issue is with the path to the command itself, not any of the arguments
I've tried quoting the command. It causes a [Error 123] The filename, directory name, or volume label syntax is incorrect error
I'm using no shell argument (so shell=false)
In case it matters, I'm grabbing a pipe to stderr for processing it, but ignoring stdout and stdin
It is only for use on Windows currently, and works as expected in all other cases that I've tested so far.
The command that is failing is:
p = subprocess.Popen(prog, stderr = subprocess.PIPE, bufsize=-1)
when the first element of the list 'prog' contains any ampersands. Quoting this first string does not work.

Make sure you are using lists and no shell expansion:
subprocess.Popen(['command', 'argument1', 'argument2'], shell=False)

Try quoting the argument that contains the &
wget "http://foo.com/?bar=baz&baz=bar"
Is usually what has to be done in a Linux shell

To answer my own question:
Quoting the actual command when passing the parameters as a list doesn't work correctly (command is first item of list) so to solve the issue I turned the list into a space separated string and passed that into subprocess instead.
Better solutions still welcomed.

"escaping the ampersand with ^"
Are you sure ^ is an escape character to Windows? Shouldn't you use \?

I try a situation as following:
exe = 'C:/Program Files (x86)/VideoLAN/VLC/VLC.exe'
url = 'http://translate.google.com/translate_tts?tl=en&q=hello+world'
subprocess.Popen([exe, url.replace("&","^&")],shell=True)
This does work.

Related

How can I enter "&" into my Java Scanner without getting a (presumed) bash error? [duplicate]

I'm currently having a major issue with a python script. The script runs arbitrary commands through a handler to convert incorrect error reporting into correct error reporting.
The issue I'm having is getting the script to work correctly on windows with a command that contains ampersands in it's path. I've attempted quoting the command, escaping the ampersand with ^ and neither works. I'm now out of ideas. Any suggestions?
To clarify from current responses:
I am using the subprocess module
I am passing the command line + arguments in as a list
The issue is with the path to the command itself, not any of the arguments
I've tried quoting the command. It causes a [Error 123] The filename, directory name, or volume label syntax is incorrect error
I'm using no shell argument (so shell=false)
In case it matters, I'm grabbing a pipe to stderr for processing it, but ignoring stdout and stdin
It is only for use on Windows currently, and works as expected in all other cases that I've tested so far.
The command that is failing is:
p = subprocess.Popen(prog, stderr = subprocess.PIPE, bufsize=-1)
when the first element of the list 'prog' contains any ampersands. Quoting this first string does not work.
Make sure you are using lists and no shell expansion:
subprocess.Popen(['command', 'argument1', 'argument2'], shell=False)
Try quoting the argument that contains the &
wget "http://foo.com/?bar=baz&baz=bar"
Is usually what has to be done in a Linux shell
To answer my own question:
Quoting the actual command when passing the parameters as a list doesn't work correctly (command is first item of list) so to solve the issue I turned the list into a space separated string and passed that into subprocess instead.
Better solutions still welcomed.
"escaping the ampersand with ^"
Are you sure ^ is an escape character to Windows? Shouldn't you use \?
I try a situation as following:
exe = 'C:/Program Files (x86)/VideoLAN/VLC/VLC.exe'
url = 'http://translate.google.com/translate_tts?tl=en&q=hello+world'
subprocess.Popen([exe, url.replace("&","^&")],shell=True)
This does work.

python: How does subprocess.check_output create it's calls?

I'm trying to read the duration of video files using mediainfo. This shell command works
mediainfo --Inform="Video;%Duration/String3%" file
and produces an output like
00:00:33.600
But when I try to run it in python with this line
subprocess.check_output(['mediainfo', '--Inform="Video;%Duration/String3%"', file])
the whole --Inform thing is ignored and I get the full mediainfo output instead.
Is there a way to see the command constructed by subprocess to see what's wrong?
Or can anybody just tell what's wrong?
Try:
subprocess.check_output(['mediainfo', '--Inform=Video;%Duration/String3%', file])
The " in your python string are likely passed on to mediainfo, which can't parse them and will ignore the option.
These kind of problems are often caused by shell commands requiring/swallowing various special characters. Quotes such as " are often removed by bash due to shell magic. In contrast, python does not require them for magic, and will thus replicate them the way you used them. Why would you use them if you wouldn't need them? (Well, d'uh, because bash makes you believe you need them).
For example, in bash I can do
$ dd of="foobar"
and it will write to a file named foobar, swallowing the quotes.
In python, if I do
subprocess.check_output(["dd", 'of="barfoo"', 'if=foobar'])
it will write to a file named "barfoo", keeping the quotes.

Execute windows command from python3.4

I have a command which I use for deployment from windows command line. Now I need to run the same from an external python3.4 script.
The command is C:\Program Files (x86)\MSBuild\12.0\Bin\msbuild "D:\WebService\WebService.sln" /p:DeployOnBuild=true /p:PublishProfile="D:\WebService\Properties\PublishProfiles\MyDeployment.pubxml" /p:AllowUntrustedCertificate=true /p:UserName=name /p:Password=PASSWORD.
How can I achieve this. I tried subprocess . But it's not working.Please help me out.
Your problems appear to be the \ and " characters, so use raw strings. Also, it is safer to use a list:
proc = subprocess.Popen(
[r"C:\Program Files (x86)\MSBuild\12.0\Bin\msbuild",
r"D:\WebService\WebService.sln",
r"/p:DeployOnBuild=true",
r"/p:PublishProfile=D:\WebService\Properties\PublishProfiles\MyDeployment.pubxml",
r"/p:AllowUntrustedCertificate=true",
r"/p:UserName=name",
r"/p:Password=PASSWORD"])
proc.wait()
Strictly speaking you don't need raw strings for all those parameters, but it is safer to do so with Windows paths. You only need the internal double quotes if you have embedded whitespace (as the first parameter). Here we are not using a shell, set shell=True as a parameter if you need one. A reason to use a shell on Windows is for filename association, but you don't appear to be using that here.
Can you post some code with what you have tried so far?
The subprocess module should be able to handle that, with something like
theproc = subprocess.Popen(["COMMAND HERE"])
theproc.communicate()
or you could try with the shell flag
theproc = subprocess.Popen(["COMMAND HERE"], shell=True)

cupsfilter Does Not Work With Python subprocess.call()

After reading this question, I've been experimenting and using subprocess.call() in Python to run a command as if from the terminal. I've found it works quite well and I prefer it over os.system. I've run into a problem with cupsfilter, though. I'm trying to run this command on OS X, from Python:
cupsfilter -o cpi=10 PDFTestIn.txt 2>PDFTestError.txt >PDFTestOut.pdf
(I tried it, originally, with more than one option, but am limiting it to one option until I can get it working.)
I can run the command fine from the command line and from os.system, but I'm having trouble with this command in subprocess.call(). I've been experimenting in IDLE and cupsfilter does not work with this as other programs do. If I provide options in the form:
-o optionname=optionvalue
I always get error messages. I tried this:
import subprocess
import os
cmd = '/usr/sbin/cupsfilter'
args = ['-o cpi=10']
ifile='PDFTestIn.txt'
ofile='PDFTestOut.pdf'
efile='PDFTestError.txt'
cmdargs = [cmd] + args + [ifile]
with open(ofile, 'w') as pdfout, open(efile, 'w') as errout:
subprocess.call(cmdargs, stdout=pdfout, stderr=errout)
When I do that, I get a return value of 1 from the last command. I check PDFTestError.txt for output and it reads:
cupsfilter: Unknown option " ".
I experimented by changing the 4th line to this:
args = ['-ocpi=10']
and I get this error:
cupsfilter: Unknown option "c".
Whatever character comes after the "-o" is seen as an option, and only that one letter is acknowledged, not the word (like "cpi"). Even though there are other options I can use besides "-o," I thought I'd try it without the "-o" just in case. When I do that, I get this error:
cupsfilter: Only one filename can be specified.
(And if I use only the command as an argument in the list passed to subprocess.call(), and still specify stdout and stderr, it works okay.)
Summary: When I use "-o" to provide an option for cupsfilter, in subprocess.call(), cupsfilter looks only at the next character, not the next word. If I have a space after "-o" as I would on the command line, it expects that space to be an option. If I leave the space out, it looks at the next character and not the next word. If I leave out "-o" it sees the option as another file name (as I'd expect).
But if I use the command line, above, from a terminal, or from os.system(), there's no problem at all.
Why won't this work with subprocess.call() and is there a way to correct that?
You need to separate each arg, '-o cpi=10' -> '-o', 'cpi=10':
subprocess.call([cmd,'-o','cpi=10',infile], stdout=pdfout, stderr=errout)

Passing Python variable to Powershell parameter using Python's Popen

I am calling a Powershell script within a Python script using Python's subprocess Popen. The Powershell script requires two input parameters: -FilePath and -S3Key. It uploads a file to AWS S3 server. If I pass in hard coded strings, the script works.
os.Popen([r'C:\\WINDOWS\\system32\\WindowsPowerShell\\v1.0\\powershell.exe','-ExecutionPolicy','RemoteSigned','./Upload.ps1 -FilePath \"C:\TEMP\test.txt\" -S3Key \"mytrialtest/test.txt\"'])
However, if I try to pass in Python string variable, the Powershell script errors out saying it can not find the file specified by the filename variable.
filename = 'C:\TEMP\test.txt'
uploadkey = 'mytrialtest/test.txt'
os.Popen([r'C:\\WINDOWS\\system32\\WindowsPowerShell\\v1.0\\powershell.exe','-ExecutionPolicy','RemoteSigned','./Upload.ps1 -FilePath \"filename\" -S3Key \"uploadkey\"'])
Any help would be greatly appreciated. Thanks.
I know, it's an old question, so this is for those who find this question via google:
The solution mentioned in comment has some risks (string injection) and might not work if there are special characters involved. Better:
import subprocess
filename = r'C:\TEMP\test.txt'
uploadkey = 'mytrialtest/test.txt'
subprocess.Popen(['powershell',"-ExecutionPolicy","RemoteSig‌​ned","-File", './Upload.ps1', '-FilePath:', filename , '-S3Key:', uploadkey])
Notice the : appended to the parameter names - in most cases it will also work without the :, but if the value starts with a dash, it will fail without the :.

Categories

Resources