I'm looking for a way to pass an argument which contains double quotes to python's subprocess module, without the double quotes being escaped.
I've seen this question asked a few different times when the quotes are surrounding the arg, but the answer is usually to remove the quotes. The issue I've hit is that the quotes are part of the argument and must be passed to the script without prepending a back slash to each quote
example:
I'm calling subprocesTest.bat, a simple batch script that takes an argument and echos it:
echo "%~1"
I invoke the batch script from python with an arg that includes quotes:
import subprocess
test_string = 'Bill said "Hi!"'
cmd = ["subprocesTest.bat",
test_string
]
p = subprocess.Popen(cmd)
p.wait()
expected output:
"Bill said "Hi!""
actual output:
"Bill said \"Hi!\""
I can get the expected output when calling the same batch script from the command line as follows:
subprocesTest.bat "Bill said "Hi!""
Looking at the source, subprocess.py's list2cmdline function is documented with:
3) A double quotation mark preceded by a backslash is
interpreted as a literal double quotation mark.
However, if I step through this function, I see no means of passing a double quote through without prepending a backslash:
elif c == '"':
# Double backslashes.
result.append('\\' * len(bs_buf)*2)
bs_buf = []
result.append('\\"')
So I have two questions...
Here are other threads where this question is asked, and worked around by not using quotes:
I see no response for a situation where I actually want to pass quotes in my argument
1) Yes, but maybe not on windows and/or with a .bat file. For example, what happens when you run the windows equivalent of this:
import subprocess
test_string = 'Bill said "Hi!"'
cmd = ["./myprog.py",
test_string
]
p = subprocess.Popen(cmd)
p.wait()
myprog.py:
#!/usr/bin/env python
import sys
print '"{}"'.format(sys.argv[1])
2) Well, the following seems a bit ambiguous:
"Bill said "Hi!""
Is that the quoted string:
"Bill said "
followed by the unquoted string:
Hi!
followed by a quoted blank string:
""
?