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

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.

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.

How to run a command line in Python

I am trying to execute
"C:/Program Files/AnsysEM/AnsysEM15.0/Win64/Designer.exe" -runscriptandexit "C:/Python27/simula_SIR_Phyton.py"
that is a to run a script in a program and I am not able to do it. I have succeed to run a single file like:
os.startfile("C:/Users/amrodri.UPVNET/Desktop/Scripts/SIR_europea_script.adsn")
But I have not succeed with the other problem. Can anyone help?
I have tried among others:
os.system("C:/Program Files/AnsysEM/AnsysEM15.0/Win64/Designer.exe" -runscriptandexit "C:/Python27/simula_SIR_Phyton.py")
os.system takes a single string as an argument. In order to have double quotes within a Python string (without terminating the string), you need to escape them using a backslash, like this:
os.system("\"C:/Program Files/AnsysEM/AnsysEM15.0/Win64/Designer.exe\" -runscriptandexit \"C:/Python27/simula_SIR_Phyton.py\"")
Or, alternatively, use single quotes instead:
os.system("'C:/Program Files/AnsysEM/AnsysEM15.0/Win64/Designer.exe' -runscriptandexit 'C:/Python27/simula_SIR_Phyton.py'")
See:
os.system()
Using quotes at the command line (This is Unix-specific, but should also apply to Windows if you're using something like PowerShell)
the culprit here is the space between Program and files. In windows, when you want to execute an address with an space in it, you need to put it between "", which is going to get mixed with Python's quotations. An easy solution would be to use raw '' in Python. For example:
import os
ansysedt_exe = r'"C:\Program Files\AnsysEM\AnsysEM16.0\Win64\ansysedt.exe" -runscriptandexit C:\automation\test_1.py'
print ansysedt_exe
os.system(ansysedt_exe)
Please notice that the designer address was put between "c:\...\designer.exe" because of the space in program files folder name, but we don't have to do the same for the script address, because there is no space there. Also just a heads up, in R16, designer.exe is going to be merged with AnsysEDT.exe.

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 :.

Passing a multi-line string as an argument to a script in Windows

I have a simple python script like so:
import sys
lines = sys.argv[1]
for line in lines.splitlines():
print line
I want to call it from the command line (or a .bat file) but the first argument may (and probably will) be a string with multiple lines in it. How does one do this?
Of course, this works:
import sys
lines = """This is a string
It has multiple lines
there are three total"""
for line in lines.splitlines():
print line
But I need to be able to process an argument line-by-line.
EDIT: This is probably more of a Windows command-line problem than a Python problem.
EDIT 2: Thanks for all of the good suggestions. It doesn't look like it's possible. I can't use another shell because I'm actually trying to invoke the script from another program which seems to use the Windows command-line behind the scenes.
I know this thread is pretty old, but I came across it while trying to solve a similar problem, and others might as well, so let me show you how I solved it.
This works at least on Windows XP Pro, with Zack's code in a file called
"C:\Scratch\test.py":
C:\Scratch>test.py "This is a string"^
More?
More? "It has multiple lines"^
More?
More? "There are three total"
This is a string
It has multiple lines
There are three total
C:\Scratch>
This is a little more readable than Romulo's solution above.
Just enclose the argument in quotes:
$ python args.py "This is a string
> It has multiple lines
> there are three total"
This is a string
It has multiple lines
there are three total
The following might work:
C:\> python something.py "This is a string^
More?
More? It has multiple lines^
More?
More? There are three total"
This is the only thing which worked for me:
C:\> python a.py This" "is" "a" "string^
More?
More? It" "has" "multiple" "lines^
More?
More? There" "are" "three" "total
For me Johannes' solution invokes the python interpreter at the end of the first line, so I don't have the chance to pass additional lines.
But you said you are calling the python script from another process, not from the command line. Then why don't you use dbr' solution? This worked for me as a Ruby script:
puts `python a.py "This is a string\nIt has multiple lines\nThere are three total"`
And in what language are you writing the program which calls the python script? The issue you have is with argument passing, not with the windows shell, not with Python...
Finally, as mattkemp said, I also suggest you use the standard input to read your multi-line argument, avoiding command line magic.
Not sure about the Windows command-line, but would the following work?
> python myscript.py "This is a string\nIt has multiple lines\there are three total"
..or..
> python myscript.py "This is a string\
It has [...]\
there are [...]"
If not, I would suggest installing Cygwin and using a sane shell!
Have you tried setting you multiline text as a variable and then passing the expansion of that into your script. For example:
set Text="This is a string
It has multiple lines
there are three total"
python args.py %Text%
Alternatively, instead of reading an argument you could read from standard in.
import sys
for line in iter(sys.stdin.readline, ''):
print line
On Linux you would pipe the multiline text to the standard input of args.py.
$ <command-that-produces-text> | python args.py

Python subprocess issue with ampersands

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.

Categories

Resources