Discussion:
Spaces in path name
joep
2008-03-16 15:41:51 UTC
Permalink
What I haven't investigated yet is whether the additional flags
your example is passing (shell=True etc.) cause the main Popen
mechanism to take a different path.
Sure enough, passing shell=True -- which is probably quite
a rare requirement -- causes the code to change the call
from "a.exe b.doc" to '%COMSPEC% /c "a.exe" "b.doc"'.
The quoting rules (from cmd /?) are slightly involved but
I can't see at first why this shouldn't work. However it
clearly doesn't so I'll try to put together either a patch
to the subprocess code or to the docs warning of the behaviour.
I think that, in general, you need to pass shell=True far less
often that you might imagine. (Possibly only for internal
commands like dir, copy etc.).
TJG
Thanks, I didn't know it is possible to drop the shell=True. The
explanation of the subprocess model are not very clear to me and the
examples are quite incomplete. I got it to work by trial and error and
looking at the usage in different packages.

Dropping shell=True works well for my case, no error messages and it
still captures the standard output:

p = subprocess.Popen([
r"C:\Program Files\WinRAR\Rar.exe","v",
r"C:\temp\Copy of papers.rar"], stdout=subprocess.PIPE)

I am still looking at different versions, and the cases when it works
and when it doesn't are still confusing.

Josef
David S
2008-03-13 22:16:57 UTC
Permalink
Hi,

I have some code in which I have to change some path names to get it to
work. The original code seems to have assumed that path names would not have
any embedded spaces.

I am not sure how to write the following line so when used in my script the
path will be found.

ANT_CMD = r'C:\Program Files\apache-ant-1.7.0\bin\ant'

Regards,
David
Tim Golden
2008-03-16 14:09:30 UTC
Permalink
subprocess.call ([
r"C:\Program Files\Adobe\Acrobat 5.0\Reader\acro reader.exe",
r"C:\Program Files\Adobe\Acr
obat 5.0\Reader\plug_ins.donotuse\Annotations\Stamps\abc def.pdf"
])
Can you confirm that something equivalent *doesn't* work on your
setup? Or have I misunderstood your point earlier? I'd really
like to get to the point where we can definitively state: this
works (and possibly: that doesn't).
Thanks
TJG
This works without problems for me on Windows XP, Python 2.4.3
OK. That's good, at least.
I often had problems understanding subprocess.Popen and getting it to
work.
I usually have to go back-and-forth between worked examples,
I admit.

[... snip problem with Popen ...]

Ah. I assumed that .call simply handed off to Popen.
I'll do some looking into that in case I need to add
a warning to the webpage. (And, maybe, a bug report).

Thanks for following this up.

TJG
Tim Golden
2008-03-14 12:03:56 UTC
Permalink
Gets me further but still seems to be issue with space after 'Program' as
code tries to run 'C:\Program'. Don't understand what is going on here...
Slight apologies as I haven't followed this thread closely, but using
the Acrobat Reader executable, which is, I think, good enough for the
purposes of illustration:

<code>
import os
import subprocess

filename = r"C:\Program Files\Adobe\Reader 8.0\Reader\AcroRd32.exe"
doc = r"C:\Program Files\Adobe\Reader 8.0\Resource\ENUtxt.pdf"

print os.path.isfile (filename)

os.system (filename + " " + doc)

os.system ('"%s" "%s"' % (filename, doc))

subprocess.call ([filename, doc])

</code>

os.path.isfile succeeds
os.system (filename) fails as your code does
os.system ('"%s"' ...) fails even though both strings are requoted
subprocess.call (filename) succeeds

The latter, at least, is because the subprocess module
has some special-case handling for exactly this situation
on MS Windows, while os.system doesn't.

Now, ultimately, I don't know if this really helps your
exact situation but it least it should be clear what will
and what won't work. Conclusion: use subprocess.call if
you can.

TJG
Mensanator
2008-03-13 23:32:43 UTC
Permalink
Post by David S
Hi,
I have some code in which I have to change some path names to get it to
work. The original code seems to have assumed that path names would not have
any embedded spaces.
I am not sure how to write the following line so when used in my script the
path will be found.
ANT_CMD ?= r'C:\Program Files\apache-ant-1.7.0\bin\ant'
Try ANT_CMD = r'"C:\Program Files\apache-ant-1.7.0\bin\ant"'
Post by David S
Regards,
David
Tim Golden
2008-03-16 06:44:20 UTC
Permalink
http://timgolden.me.uk/python/win32_how_do_i/run-a-command-with-a-spa...
Note: this works for subprocess.call but for subprocess.Popen this
does not work if there are two arguments in the command line with
spaces. Especially, even after trying out many different versions, I
never managed to get subprocess.Popen to work, when both the
executable and one argument have spaces in the file path.
Sorry, incomplete sentence
Especially, even after trying out many different versions, I never
managed to get subprocess.Popen to work '''when command line is given
as a *list* argument to subprocess.Popen'''
in the case when both the executable and one argument have spaces in
the file path.
Thanks for the info. I'll get on the case and put some examples
together with caveats.

TJG
joep
2008-03-16 13:23:21 UTC
Permalink
subprocess.call ([
r"C:\Program Files\Adobe\Acrobat 5.0\Reader\acro reader.exe",
r"C:\Program Files\Adobe\Acr
obat 5.0\Reader\plug_ins.donotuse\Annotations\Stamps\abc def.pdf"
])
Can you confirm that something equivalent *doesn't* work on your
setup? Or have I misunderstood your point earlier? I'd really
like to get to the point where we can definitively state: this
works (and possibly: that doesn't).
Thanks
TJG
This works without problems for me on Windows XP, Python 2.4.3

In the past, I didn't have problems with subprocess.call, and I never
had to look closer to the different versions of quoting.

I often had problems understanding subprocess.Popen and getting it to
work. For example the equivalent case for popen, as your
subprocess.call example, does not work, or I'm making a different
mistake with subprocess.Popen:

p = subprocess.Popen([
r"C:\Program Files\WinRAR\Rar.exe",
r"C:\temp\Copy of papers.rar"],
shell=True, stdout=subprocess.PIPE)
rettext,reterror = p.communicate()
retcode = p.wait()
p.stdout.close()

results in:
'C:\Program' is not recognized as an internal or external command,
operable program or batch file.

I assume that there is some difference how subprocess.call and
subprocess.Popen handle and format the command. subprocess.Popen does
the correct formatting when only one file path has spaces and requires
double quoting, but not if there are two file paths with spaces in it.

Josef
Tim Golden
2008-03-16 14:30:11 UTC
Permalink
Post by joep
I assume that there is some difference how subprocess.call and
subprocess.Popen handle and format the command. subprocess.Popen does
the correct formatting when only one file path has spaces and requires
double quoting, but not if there are two file paths with spaces in it.
The briefest of code explorations shows that subprocess.call simply
hands straight off to Popen, passing args & kwargs along verbatim,
and then calls .wait on the result. ie, this:

subprocess.call (['a.exe', 'b.doc'])

simply becomes:

subprocess.Popen (['a.exe', 'b.doc']).wait ()

What I haven't investigated yet is whether the additional flags
your example is passing (shell=True etc.) cause the main Popen
mechanism to take a different path. I'll spend some time on
that this pm, unless someone gets in first with more of a clue
than I currently have.

TJG
Tim Golden
2008-03-16 14:54:16 UTC
Permalink
What I haven't investigated yet is whether the additional flags
your example is passing (shell=True etc.) cause the main Popen
mechanism to take a different path.
Sure enough, passing shell=True -- which is probably quite
a rare requirement -- causes the code to change the call
from "a.exe b.doc" to '%COMSPEC% /c "a.exe" "b.doc"'.
The quoting rules (from cmd /?) are slightly involved but
I can't see at first why this shouldn't work. However it
clearly doesn't so I'll try to put together either a patch
to the subprocess code or to the docs warning of the behaviour.

I think that, in general, you need to pass shell=True far less
often that you might imagine. (Possibly only for internal
commands like dir, copy etc.).

TJG
Tim Golden
2008-03-16 07:42:31 UTC
Permalink
http://timgolden.me.uk/python/win32_how_do_i/run-a-command-with-a-spa...
Note: this works for subprocess.call but for subprocess.Popen this
does not work if there are two arguments in the command line with
spaces. Especially, even after trying out many different versions, I
never managed to get subprocess.Popen to work, when both the
executable and one argument have spaces in the file path.
Sorry, incomplete sentence
Especially, even after trying out many different versions, I never
managed to get subprocess.Popen to work '''when command line is given
as a *list* argument to subprocess.Popen'''
in the case when both the executable and one argument have spaces in
the file path.
Following up, I'm a little bemused. Below is a command which works on
a Win2K Python 2.4 installation (and on WinXP with Python 2.5).
I've deliberately chosen something in Program Files and I've copied both
the executable and the document so that even the base filenames have
embedded spaces, as well as the directory path to get there.
(The lines are quite long: you'll probably have to piece them
together a bit; that's why I've put an extra line space between
each.)

subprocess.call ([

r"C:\Program Files\Adobe\Acrobat 5.0\Reader\acro reader.exe",

r"C:\Program Files\Adobe\Acr
obat 5.0\Reader\plug_ins.donotuse\Annotations\Stamps\abc def.pdf"

])

Can you confirm that something equivalent *doesn't* work on your
setup? Or have I misunderstood your point earlier? I'd really
like to get to the point where we can definitively state: this
works (and possibly: that doesn't).

Thanks
TJG
joep
2008-03-15 21:47:08 UTC
Permalink
http://timgolden.me.uk/python/win32_how_do_i/run-a-command-with-a-spa...
Note: this works for subprocess.call but for subprocess.Popen this
does not work if there are two arguments in the command line with
spaces. Especially, even after trying out many different versions, I
never managed to get subprocess.Popen to work, when both the
executable and one argument have spaces in the file path.
Sorry, incomplete sentence

Especially, even after trying out many different versions, I never
managed to get subprocess.Popen to work '''when command line is given
as a *list* argument to subprocess.Popen'''
in the case when both the executable and one argument have spaces in
the file path.

joe
David S
2008-03-15 00:15:47 UTC
Permalink
By mapping network drives in windows I can get past these issues with path
names.

Thanks,
David

"Tim Golden" <mail at timgolden.me.uk> wrote in message
Gets me further but still seems to be issue with space after 'Program' as
code tries to run 'C:\Program'. Don't understand what is going on here...
Slight apologies as I haven't followed this thread closely, but using the
Acrobat Reader executable, which is, I think, good enough for the
<code>
import os
import subprocess
filename = r"C:\Program Files\Adobe\Reader 8.0\Reader\AcroRd32.exe"
doc = r"C:\Program Files\Adobe\Reader 8.0\Resource\ENUtxt.pdf"
print os.path.isfile (filename)
os.system (filename + " " + doc)
os.system ('"%s" "%s"' % (filename, doc))
subprocess.call ([filename, doc])
</code>
os.path.isfile succeeds
os.system (filename) fails as your code does
os.system ('"%s"' ...) fails even though both strings are requoted
subprocess.call (filename) succeeds
The latter, at least, is because the subprocess module
has some special-case handling for exactly this situation
on MS Windows, while os.system doesn't.
Now, ultimately, I don't know if this really helps your
exact situation but it least it should be clear what will
and what won't work. Conclusion: use subprocess.call if
you can.
TJG
joep
2008-03-15 21:42:07 UTC
Permalink
http://timgolden.me.uk/python/win32_how_do_i/run-a-command-with-a-spa...
Note: this works for subprocess.call but for subprocess.Popen this
does not work if there are two arguments in the command line with
spaces. Especially, even after trying out many different versions, I
never managed to get subprocess.Popen to work, when both the
executable and one argument have spaces in the file path.

subprocess.Popen requires the same extra double quoting at front or
around the entire command as os.system. It took me many hours to find
the versions of quoting that work. Explanation by Fredrik Lundh
in thread
http://groups.google.com/group/comp.lang.python/browse_thread/thread/775ca566af9a70c2/65504296a27b43d5?lnk=gst&q=subprocess+windows+spaces#65504296a27b43d5

Here is a test file checking several cases:

<code>
'''use winrar to get file information of a rar file
testing double quotes for windows file paths with spaces using
subprocess.Popen

see:
http://groups.google.com/group/comp.lang.python/browse_thread/thread/775ca566af9a70c2/65504296a27b43d5?lnk=gst&q=subprocess+windows+spaces#65504296a27b43d5

result:
* most robust: use double quotes around entire command string
* command as list argument never works when 2 file paths have spaces
'''
import sys, os
import subprocess

def rargetinfo(filename,version=0):
'''use winrar to get file information of a rar file
'''
if version == 0:
rarcmd = '"%s %s %s ' % (r'"C:\Program Files\WinRAR\Rar.exe"',
"v", filename)
elif version == 1:
rarcmd = '"%s %s %s" ' % (r'"C:\Program Files\WinRAR
\Rar.exe"', "v", filename)
elif version == 2:
rarcmd = '%s %s %s ' % (r'"C:\Program Files\WinRAR\Rar.exe"',
"v", filename)
elif version == 3:
rarcmd = [r'"C:\Program Files\WinRAR\Rar.exe"', "v",
filename]
elif version == 4:
executable_name = os.path.join(r'C:\Program Files\WinRAR',
'Rar.exe')
rarcmd = [executable_name, "v", filename]

p = subprocess.Popen(rarcmd, shell=True, stdout=subprocess.PIPE)
rettext,reterror = p.communicate()
retcode = p.wait()
p.stdout.close()
print rarcmd
print 'this is rettext',rettext[:50]
return rettext, rarcmd


filenames = [r'"C:\temp\Copy of papers.rar"']
filenames.append(r'"C:\temp\papers.rar"')
filenames.append(r'C:\temp\papers.rar')

positives = {}
negatives = {}

for filename in filenames:
for version in range(5):
print '\n%s version: %d' % (filename,version)
rettext, cmd = rargetinfo(filename,version)
if rettext :
print 'success'
positives.setdefault(version,[]).append(cmd)
else:
print 'failure'
negatives.setdefault(version,[]).append(cmd)
from pprint import pprint
print 'positives:'
pprint(positives)
print 'negatives:'
pprint(negatives)
</code>
joep
2008-03-15 01:05:31 UTC
Permalink
Post by David S
By mapping network drives in windows I can get past these issues with path
names.
Thanks,
David
"Tim Golden" <m... at timgolden.me.uk> wrote in message
Gets me further but still seems to be issue with space after 'Program' as
code tries to run 'C:\Program'. Don't understand what is going on here...
Slight apologies as I haven't followed this thread closely, but using the
Acrobat Reader executable, which is, I think, good enough for the
<code>
import os
import subprocess
filename = r"C:\Program Files\Adobe\Reader 8.0\Reader\AcroRd32.exe"
doc = r"C:\Program Files\Adobe\Reader 8.0\Resource\ENUtxt.pdf"
print os.path.isfile (filename)
os.system (filename + " " + doc)
os.system ('"%s" "%s"' % (filename, doc))
subprocess.call ([filename, doc])
</code>
os.path.isfile succeeds
os.system (filename) fails as your code does
os.system ('"%s"' ...) fails even though both strings are requoted
subprocess.call (filename) succeeds
The latter, at least, is because the subprocess module
has some special-case handling for exactly this situation
on MS Windows, while os.system doesn't.
Now, ultimately, I don't know if this really helps your
exact situation but it least it should be clear what will
and what won't work. Conclusion: use subprocess.call if
you can.
TJG
I had the same problem recently with subprocess.popen, when there is a
space in the executable and a space in an additional argument as in
the acrobat example. I finally found a past thread in this news group
that explained that you have to use two (2) leading double quotes, and
as on the command line all arguments with spaces have to be quoted.

All three examples with acrobat work on my WindowsXP in this case
(opens Acrobat three times, after closing previous):

<code>
import os
import subprocess

filename = r"C:\Program Files\Adobe\Acrobat 7.0\Acrobat\Acrobat.exe"
doc = r"C:\Program Files\Adobe\Acrobat 7.0\Help\ENU\Pdfmark.pdf"

print os.path.isfile (filename)
print 'case 1'
os.system ('""' + filename + '" "' + doc + '"') # quotes split up for
clarity: (' " " ' + filename + ' " " ' + doc + ' " ')
print 'case 2'
os.system ('""%s" "%s"' % (filename, doc))
print 'case 3'
subprocess.call ([filename, doc])

</code>

Josef
Tim Golden
2008-03-15 12:08:21 UTC
Permalink
Post by joep
I had the same problem recently with subprocess.popen, when there is a
space in the executable and a space in an additional argument as in
the acrobat example. I finally found a past thread in this news group
that explained that you have to use two (2) leading double quotes, and
as on the command line all arguments with spaces have to be quoted.
Thanks for this, joep. I've added a how-do-i to my website
covering the different cases, I hope. This comes up often
enough that maybe next time we can just point someone there
first time!

TJG

http://timgolden.me.uk/python/win32_how_do_i/run-a-command-with-a-space-in-it.html
David S
2008-03-14 11:38:31 UTC
Permalink
Hi,

Gets me further but still seems to be issue with space after 'Program' as
code tries to run 'C:\Program'. Don't understand what is going on here...

using "java.exe" from "C:\Program Files\Java\jdk1.6.0_01"
using "C:\Program Files\apache-ant-1.7.0\bin\ant.bat" for building
Building from E:\Red5\red5_server\install\windows
Cleaning old directories...
Compiling Java 1.5 version...
'C:\Program' is not recognized as an internal or external command,
operable program or batch file.
Traceback (most recent call last):
File "installer.py", line 132, in <module>
main()
File "installer.py", line 128, in main
builder.build()
File "installer.py", line 70, in build
self.compile(self.ant_cmd, os.path.join(red5_root, 'build.xml'), '1.5',
'cle
an', 'installerdist')
File "installer.py", line 26, in compile
assert os.system('%s -quiet -Djava.target_version=%s -buildfile %s%s' %
(ant
, version, script, args)) == 0
AssertionError


"Bryan Olson" <fakeaddress at nowhere.org> wrote in message
I get
ERROR: ""C:\Program Files\apache-ant-1.7.0\bin\ant"" does not exist
If I cut the path statement here and paste it next to a windows XP
command prompt ant is invoked.
The python code here is
error('"%s" does not exist' % ANT_CMD)
Post by Tim Golden
import os
os.path.isfile(r'C:\Program Files\Windows NT\dialer.exe')
True
Post by Tim Golden
print os.path.isfile(r'"C:\Program Files\Windows NT\dialer.exe"')
False
--
--Bryan
David S
2008-03-14 04:37:12 UTC
Permalink
Hi,

I get

ERROR: ""C:\Program Files\apache-ant-1.7.0\bin\ant"" does not exist

If I cut the path statement here and paste it next to a windows XP command
prompt ant is invoked.

The python code here is
if not os.path.isfile(ANT_CMD):
error('"%s" does not exist' % ANT_CMD)

David

"Mensanator" <mensanator at aol.com> wrote in message
Post by David S
Hi,
I have some code in which I have to change some path names to get it to
work. The original code seems to have assumed that path names would not have
any embedded spaces.
I am not sure how to write the following line so when used in my script the
path will be found.
ANT_CMD = r'C:\Program Files\apache-ant-1.7.0\bin\ant'
Try ANT_CMD = r'"C:\Program Files\apache-ant-1.7.0\bin\ant"'
Post by David S
Regards,
David
Bryan Olson
2008-03-14 08:25:07 UTC
Permalink
Using "C:\Program Files\apache-ant-1.7.0\bin\ant.bat" just gives me the same
result.
Did you try the raw string, with the .bat extension? As in:

r'C:\Program Files\apache-ant-1.7.0\bin\ant.bat'


After Microsoft started allowing blanks in paths, it took them years to
fix many common cases where their own software choked on the paths. I
got into the habit of installing everything under c:\bin rather than
C:\Program Files. I still do that just to avoid writing essays into
my PATH variable.
--
--Bryan
Bryan Olson
2008-03-14 08:18:51 UTC
Permalink
I get
ERROR: ""C:\Program Files\apache-ant-1.7.0\bin\ant"" does not exist
If I cut the path statement here and paste it next to a windows XP command
prompt ant is invoked.
The python code here is
error('"%s" does not exist' % ANT_CMD)
Post by Tim Golden
import os
os.path.isfile(r'C:\Program Files\Windows NT\dialer.exe')
True
Post by Tim Golden
print os.path.isfile(r'"C:\Program Files\Windows NT\dialer.exe"')
False
--
--Bryan
David S
2008-03-14 07:31:08 UTC
Permalink
Hi,

Using "C:\Program Files\apache-ant-1.7.0\bin\ant.bat" just gives me the same
result.

David

"Dennis Lee Bieber" <wlfraed at ix.netcom.com> wrote in message
On Fri, 14 Mar 2008 04:37:12 GMT, "David S" <davids at evertech.com.au>
Post by David S
If I cut the path statement here and paste it next to a windows XP command
prompt ant is invoked.
The python code here is
error('"%s" does not exist' % ANT_CMD)
Any chance the /filename/ is something like "ant.exe"
Post by David S
pyt = "e:/python24/python"
... print "%s does not exist" % pyt
...
e:/python24/python does not exist
Post by David S
pyt = "e:/python24/python.exe"
... print "%s does not exist" % pyt
...
Remember, under Windows, files with certain extensions are
executable /without/ needing the extension on the command line -- unlike
Linux...
My eclipse install has: ant.bat, ant.cmd, and ant.jar files, and
which (if they are in the same directory) gets picked when the extension
is not specified is beyond my current knowledge -- might depend on the
order of the extensions specified in the
C:\Documents and Settings\Dennis Lee Bieber>echo %pathext%
.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.pyw;.py;.pyo;.pyc;.tcl
(okay, the ant.jar won't be picked <G>)
--
Wulfraed Dennis Lee Bieber KD6MOG
wlfraed at ix.netcom.com wulfraed at bestiaria.com
HTTP://wlfraed.home.netcom.com/
(Bestiaria Support Staff: web-asst at bestiaria.com)
HTTP://www.bestiaria.com/
Gertjan Klein
2008-03-17 11:11:09 UTC
Permalink
* If shell=True is required, then the executable is a build-in shell
command, which does not contain spaces, and, therefore, has no
problems
This is only true when you are referring to directly executable files.
However, Shell=True is also required when you want to "execute" a file
by it's association. For example, if you want to execute a ".pyw" file
directly (i.e., by using whichever python executable is associated with
that extension), you need Shell=True.

IMHO, the subprocess module should not have been included as-is in the
Python library. It is counter-intuitive, buggy, ill-documented, and has
needless limitations in functionality.

Regards,
Gertjan.
--
Gertjan Klein <gklein at xs4all.nl>
Tim Golden
2008-03-17 11:34:56 UTC
Permalink
Post by Gertjan Klein
* If shell=True is required, then the executable is a build-in shell
command, which does not contain spaces, and, therefore, has no
problems
This is only true when you are referring to directly executable files.
However, Shell=True is also required when you want to "execute" a file
by it's association. For example, if you want to execute a ".pyw" file
directly (i.e., by using whichever python executable is associated with
that extension), you need Shell=True.
Thanks for that clarification. I hadn't tried that path.

TJG
Tim Golden
2008-03-16 16:49:42 UTC
Permalink
Well I've got a patch ready to go (which basically just
wraps a shell=True command line with an *extra* pair of
double-quotes, the same as you do for an os.system call).
I'll try to put some time into the subprocess docs as well,
at least as far as a Win32-how-do-I on my own site if not
an update to the official docs.
For the record, I've raised this as issue 2304 with a
patch attached:

http://bugs.python.org/issue2304

TJG
Tim Golden
2008-03-16 16:22:11 UTC
Permalink
Post by joep
What I haven't investigated yet is whether the additional flags
your example is passing (shell=True etc.) cause the main Popen
mechanism to take a different path.
Sure enough, passing shell=True -- which is probably quite
a rare requirement -- causes the code to change the call
from "a.exe b.doc" to '%COMSPEC% /c "a.exe" "b.doc"'.
The quoting rules (from cmd /?) are slightly involved but
I can't see at first why this shouldn't work. However it
clearly doesn't so I'll try to put together either a patch
to the subprocess code or to the docs warning of the behaviour.
I think that, in general, you need to pass shell=True far less
often that you might imagine. (Possibly only for internal
commands like dir, copy etc.).
TJG
Thanks, I didn't know it is possible to drop the shell=True. The
explanation of the subprocess model are not very clear to me and the
examples are quite incomplete. I got it to work by trial and error and
looking at the usage in different packages.
Dropping shell=True works well for my case, no error messages and it
p = subprocess.Popen([
r"C:\Program Files\WinRAR\Rar.exe","v",
r"C:\temp\Copy of papers.rar"], stdout=subprocess.PIPE)
I am still looking at different versions, and the cases when it works
and when it doesn't are still confusing.
Well I've got a patch ready to go (which basically just
wraps a shell=True command line with an *extra* pair of
double-quotes, the same as you do for an os.system call).
I'll try to put some time into the subprocess docs as well,
at least as far as a Win32-how-do-I on my own site if not
an update to the official docs.

TJG
joep
2008-03-16 17:00:12 UTC
Permalink
One more try (using popen instead of call is not necessary for these
cases, but I want to see the behavior of popen):

shell=True and executable and at least one argument with spaces does
not work:
---------------------------------------------------------------------------------------------------------------------

p = subprocess.Popen([r"C:\Programs\GnuWin32\GetGnuWin32\gnuwin32\bin
\Copy of cp.exe",
r"C:\Temp\temp with spaces\test out.txt",
r"C:\Temp\temp with spaces\test out3.txt"],
shell=True, stdout=subprocess.PIPE)

causes:
'C:\Programs\GnuWin32\GetGnuWin32\gnuwin32\bin\Copy' is not recognized
as an int
ernal or external command, operable program or batch file.


the following all work:
================

without shell=True, and executable and at least one argument with
spaces
-----------------------------------------------------------------------------------------------------------

p = subprocess.Popen([r"C:\Programs\GnuWin32\GetGnuWin32\gnuwin32\bin
\Copy of cp.exe",
r"C:\Temp\temp with spaces\test out.txt",
r"C:\Temp\temp with spaces\test out4.txt"],
stdout=subprocess.PIPE)

with shell=True, and executable without spaces, even if two arguments
with spaces
------------------------------------------------------------------------------------------------------------------------

p = subprocess.Popen(["copy",
r"C:\Temp\temp with spaces\test out.txt",
r"C:\Temp\temp with spaces\test out2.txt"],
shell=True, stdout=subprocess.PIPE)

with shell=True, and executable without spaces, even if two arguments
with spaces
------------------------------------------------------------------------------------------------------------------------
but here shell=True is not necessary

p = subprocess.Popen([r"C:\Programs\GnuWin32\GetGnuWin32\gnuwin32\bin
\cp.exe",
r"C:\Temp\temp with spaces\test out.txt",
r"C:\Temp\temp with spaces\test out5.txt"],
shell=True, stdout=subprocess.PIPE)

without shell=True, and executable and at least one arguments with
spaces
-------------------------------------------------------------------------------------------------------------

p = subprocess.Popen([r"C:\Programs\GnuWin32\GetGnuWin32\gnuwin32\bin
\Copy of cp.exe",
r"C:\Temp\temp with spaces\test out.txt",
r"C:\Temp\temp with spaces\test out4.txt"],
stdout=subprocess.PIPE)

My conclusions:
============

Assuming shell=True is only required for build-in shell commands, non
of which has spaces.

There is no problem, if you know when *not* to use shell=True:

* More than two arguments with spaces are never problem, as long as
the executable does not have spaces
* If shell=True is required, then the executable is a build-in shell
command, which does not contain spaces, and, therefore, has no
problems
* If you use a non-build in executable, then don't use shell=True.
This works correctly even if the executable and at least one
additional argument have spaces.

It took a lot of time to figure this out, but now at least I know, how
to construct the call to subprocess.Popen, so that it works in the
cases I used it so far.

Josef
Continue reading on narkive:
Loading...