3

When I'm using Python 3 to launch a program via subprocess.call(), why do I need 4 backslashes in paths?

This is my code:

cmd = 'C:\\\\Windows\\\\System32\\\\cmd.exe'

cmd = shlex.split(cmd)

subprocess.call(cmd)

When I examine the command line of the launched cmd.exe instance with Task Manager, it shows the path correctly with only one backslash separating each path.


Because of this, I need this on Windows to make the paths work:

if platform.platform().startswith('Windows'):
    cmd = cmd.replace(os.sep, os.sep + os.sep)

is there a more elegant solution?

kiri
  • 2,522
  • 4
  • 26
  • 44

4 Answers4

4

When you are creating the string, you need to double each backslash for escaping, and then when the string is passed to your shell, you need to double each backslash again. You can cute the backslashes in half by using a raw string:

cmd = r'C:\\Windows\\System32\\cmd.exe'
John Percival Hackworth
  • 11,395
  • 2
  • 29
  • 38
  • 1
    This mostly makes sense, but if the first pair of backslashes are interpreted by Python, what interprets the 2nd pair? – kiri Nov 01 '13 at 02:52
  • @minerz029, as I explained in my answer, `shlex.split()` *also* interprets backslashes as escape characters. – Tim Peters Nov 01 '13 at 03:23
4

Part of the problem is that you're using shlex, which implements escaping rules used by Unix-ish shells. But you're running on Windows, whose command shells use different rules. That accounts for one level of needing to double backslashes (i.e., to worm around something shlex does that you didn't need to begin with).

That you're using a regular string instead of a raw string (r"...") accounts for the other level of needing to double backslashes, and 2*2 = 4. QED ;-)

This works fine on Windows:

cmd = subprocess.call(r"C:\Windows\System32\cmd.exe")

By the way, read the docs for subprocess.Popen() carefully: the Windows CreateProcess() API call requires a string for an argument. When you pass a sequence instead, Python tries to turn that sequence into a string, via rules explained in the docs. When feasible, it's better - on Windows - to pass the string you want directly.

Tim Peters
  • 67,464
  • 13
  • 126
  • 132
  • Thanks for this detailed explanation. I'll make a note not to use `shlex.split()` on Windows, only on Linux. – kiri Nov 01 '13 at 07:56
2

\ has special meaning - you're using it as part of an escape sequence. Double up the backslashes, and you have a literal backslash \.

The caveat is that, with only one pair of escaped backslashes, you still have only one literal backslash. You need to escape that backslash, too.

Alternatively, why not just use os.sep instead? You'll be able to ensure your code is more portable (since it'll use the system-specific separator), and you won't have to deal [directly] with escaping backslashes.

Makoto
  • 104,088
  • 27
  • 192
  • 230
  • `os.sep`? I've edited my question to show that I need to double `os.sep` to make the paths launch correctly. – kiri Nov 01 '13 at 02:46
  • It may be the case that you're stuck like that. [This similar question](http://stackoverflow.com/a/11924842/1079354) doesn't offer much in the way of relief either, unless you wanted to go the path of raw strings. – Makoto Nov 01 '13 at 02:48
0

As John points out 4 slashes isn't necessary when accessing files locally. One place where 4 slashes is necessary is when connecting to (generally windows) servers over SMB or CIFS.

Normally you would just use \servername\share\

But each one of those slashes needs to be escaped. So thus the 4 slashes before servernames.

you could also use subprocess.call()

import subprocess as sp
sp.call(['c:\\program files\\<path>'])
Back2Basics
  • 7,406
  • 2
  • 32
  • 45
  • I don't get what you mean. John's answer said that the 4 backslashes are a necessity and I haven't mentioned servers anywhere in my question (see my example in my question). – kiri Nov 01 '13 at 03:00
  • Your question was "why do I need 4 backslashes in paths?" Your example didn't fit the entirety of the question. So I added network paths to the realm of possibilities. – Back2Basics Nov 01 '13 at 03:30