barciewicz
barciewicz

Reputation: 3783

Why does putting Windows path into a variable does not replace a particular single slash with a double slash?

Why does the second slash does not get replaced with double slash when I do the following in Python shell?:

>>> p = 'M:\django\newenv\django_projects\mediaproject\mediaproject\media'
>>> p
'M:\\django\newenv\\django_projects\\mediaproject\\mediaproject\\media'

I think this is causing an error I am getting when trying to os.listdir(p):

FileNotFoundError: [WinError 3] The system cannot find the path specified: 'M:\\django\newenv\\django_projects\\mediaproject\\mediaproject\\media'

Or is there any other cause of the error? The directory exists for sure and is copy-pasted from Windows file explorer.

EDIT:

I think this is because the second slash preceded the n character, so it gets treated as newline character. But how do I work around that (in real world I will not be typing the path manually)?

Upvotes: 1

Views: 1221

Answers (3)

Vasu Deo.S
Vasu Deo.S

Reputation: 1850

Try

 p = r'M:\django\newenv\django_projects\mediaproject\mediaproject\media'

 os.listdir(p)

Adding a r before a string prevents escape sequence interpretation inside the string. Therefore, the string is only interpreted as a raw string.

The difference between a raw string and a normal string, is how they deal with escape sequences. A raw string will always treat a \n as two separate characters, a \ followed by a n. On the other hand a normal string will treat the \n as a single character.

EX.

raw_string = r"\n"
string = "\n"

print(len(raw_string)) 
print(len(string)) 

OUTPUT

2
1

Upvotes: 3

Serge Ballesta
Serge Ballesta

Reputation: 148910

What happens here is that '\n' is the control character NewLine, unicode U+0010. As neither '\d' nor '\m' are special they are left unchanged. It may be more clear when you try to print p:

>>> print(p)
M:\django
ewenv\django_projects\mediaproject\mediaproject\media

The \ characters that appeared as \\ are actually a single \ in the string, and \n actually is a new line.

The 2 foolproof ways to insert \ in a string are:

  • consistently double them:

    p = 'M:\\django\\newenv\\django_projects\\mediaproject\\mediaproject\\media'
    
  • use the r'...' construct:

    p = r'M:\django\newenv\django_projects\mediaproject\mediaproject\media'
    

The latter is easier when you copy/paste a path.


Beware, other \x characters are special: \a, \b, \f, \r, \t, \v. In addition, '\xab' is the character of code ab (for example '\x41' is 'A' in the ascii charset) '\uabcd' is the unicode character U+abcd, and '\U00abcdef' is the unicode character U+abcdef.

Upvotes: 2

BoboDarph
BoboDarph

Reputation: 2891

Working on the comments, I think OP needs a way to parse the MEDIA_ROOT env variable into an internal variable to his script.

To this goal, I suggest trying to get the environment variable using os.environ and parsing it into a python path with os.path.abspath. Example code below:

import os
import os.path
try:
    media_root = os.path.abspath(os.environ['MEDIA_ROOT'])
except KeyError:
    media_root = None 
    # Alternatively you can just raise the exception here if you want to halt

Alternatively, if your MEDIA_ROOT variable comes directly from django.conf.settings.MEDIA_ROOT you could, for your peace of mind, wrap it into an abspath, but I have a sneaky suspicion that django already does that for you.

Upvotes: 1

Related Questions