13

I'm writing a Python script that accepts file paths as strings, parses them, appends a command name, and builds a list, which is then passed to subprocess.Popen() for execution. This script is to handle both Unix and Windows file paths, and ultimately should run on both systems.

When I run this under Unix, if I give a Windows path that inadvertently contains an escape character (e.g. \Users\Administrator\bin), Python will interpret the embedded \b as the backspace character. I want to prevent that from happening.

As far as I know, there's no function or method to denote a string variable as a raw string. The 'r' modifier only works for string constants.

So far, the closest I've been able to get is this:

winpath = "C:\Users\Administrator\bin" 
winpath = winpath.replace('\b','\\b')
winpathlist = winpath.split('\\') 

At this point, winpathlist should contain ['C:','Users','Administrator','bin'], not ['C','Users','Administrator\x08in'].

I can add additional calls to winpath.replace() to handle the other escapes I might get -- \a, \f, \n, \r, \t, \v -- but not \x.

Is there a more pythonic way to do this?

Pierre GM
  • 19,809
  • 3
  • 56
  • 67
poltr1
  • 147
  • 1
  • 1
  • 6
  • 5
    How are you getting the value into the string? Python shouldn't treat the \b as an escape unless it's in a string literal, or gets into the string as an escape to begin with. (Also, forward slashes work just fine.) – Wooble Sep 26 '12 at 15:26
  • @Wooble: Right now, it's coming in via doctest. >>> myCommandObject.setExcecutablePath('C:\Program Files\cygwin\cdrive\bin') where myCommandObject contains a command name (e.g. 'ps'), a path, and a list of arguments. Changing the slashes from backslashes to forward slashes is not an option; my customer explicitly stated that this is what he wanted. – poltr1 Sep 26 '12 at 17:25
  • As I said, r only works for string literals; it does not work for string variables. I look at the leading r as a kluge. Anyway, here's the doctest (or part of it): >>> myCommand.setExecutablePath('C:\Program Files\cygwin\cdrive\bin') >>> myCommandList = myCommand.getLaunchList() >>> myCommandList ['C:\\\\Program Files\\\\cygwin\\\\cdrive\\\\bin\\\\ps', '-e', '-f'] >>> myCommandList[0].split("\\\\") ['C:', 'Program Files', 'cygwin', 'cdrive', 'bin', 'ps'] I'm no longer getting any errors, now that I added the call to replace. – poltr1 Sep 26 '12 at 18:00
  • Forgot to thank Wooble for the help and suggestions. After consulting with my customer, he opted to move the Windows path test out of the doctest and into a separate file. – poltr1 Sep 27 '12 at 18:17

2 Answers2

19

If your winpath is hard-coded, you may want to use r before your string to indicate it is a "raw string".

winpath = r"C:\Users\Administrator\bin"

If winpath cannot be hardcoded, you can try to create a new string as:

escaped_winpath = "%r" % winpath

(which is just repr(winpath), and won't really help you, as repr("\bin") is...)

A solution would be to rebuild the string from scratch: you can find an example of function at that link, but the generic idea is:

escape_dict={'\a':r'\a',
             '\b':r'\b',
             '\c':r'\c',
             '\f':r'\f',
             '\n':r'\n',
             '\r':r'\r',
             '\t':r'\t',
             '\v':r'\v',
             '\'':r'\'',
             '\"':r'\"'}

def raw(text):
    """Returns a raw string representation of text"""
    new_string=''
    for char in text:
        try: 
            new_string += escape_dict[char]
        except KeyError: 
            new_string += char
    return new_string

and now, raw("\bin") gives you "\\bin" (and not "\\x08in")...

Pierre GM
  • 19,809
  • 3
  • 56
  • 67
  • I'm not familiar with repr(). Is it in 2.6? I like this idea, and will hang on to this in case I need it in the future. At the request of my customer, I pulled out the calls to replace(). Instead, he suggested that I move the Windows path test out of the doctest and into a separate file. Thanks for the suggestion. – poltr1 Sep 27 '12 at 18:16
7

You can create a raw string by prepending r to the string literal notation

r"hello\nworld"

becomes

"hello\\nworld"

You can read some more here

thenoviceoof
  • 618
  • 4
  • 9