os.path.join doubt

H

harryos

In windows ,I tried this

p1 = "C:\Users\me\Documents"
p2 = "..\Pictures\images\my.jpg"

print os.path.join(p1,p2)
This gives
'C:\\Users\\me\\Documents\\..\\Pictures\\images\\my.jpg'

I expected I would get
'C:\\Users\\me\\Pictures\\images\\my.jpg'

I thought os.path.join would join the paths more intelligently..Any
idea why this happens ?
harry
 
C

Chris Rebert

In windows ,I tried this

p1 = "C:\Users\me\Documents"
p2 = "..\Pictures\images\my.jpg"

print os.path.join(p1,p2)
This gives
'C:\\Users\\me\\Documents\\..\\Pictures\\images\\my.jpg'

I expected I would get
'C:\\Users\\me\\Pictures\\images\\my.jpg'

I thought os.path.join would join the paths more intelligently..Any
idea why this happens ?

Because that's just not how the function is defined. I admit the
"intelligently" descriptor in its docs is fairly vague.
Call os.path.normpath() on the join() result to simplify the path and
obtain the form you expected.
http://docs.python.org/library/os.path.html#os.path.normpath

Cheers,
Chris
 
S

Steven D'Aprano

In windows ,I tried this

p1 = "C:\Users\me\Documents"
p2 = "..\Pictures\images\my.jpg"

print os.path.join(p1,p2)
This gives
'C:\\Users\\me\\Documents\\..\\Pictures\\images\\my.jpg'

I expected I would get
'C:\\Users\\me\\Pictures\\images\\my.jpg'

I thought os.path.join would join the paths more intelligently..Any idea
why this happens ?

You thought wrong.

os.path.join just joins what you tell it to, it doesn't normalise the
path. If you want to normalise, call os.path.normpath:

'x/z'


As for why, it's because joining and normalising are two different
operations that you may wish to keep separate, so they require two
separate functions.


BTW, Windows accepts / as well as \ as a path separator. You will have
far fewer headaches if you use that.
 
N

Nobody

Don't do this; backslash is significant within Python string literals. If
want to use literal backslashes in a string literal, either double them:

p1 = "C:\\Users\\me\\Documents"

or use a raw literal:

p1 = r"C:\Users\me\Documents"

You got away with it because backslash is only significant when followed
by specific characters, none of which occurred in this case.
BTW, Windows accepts / as well as \ as a path separator. You will have
far fewer headaches if you use that.

Unless you need to pass strings to the command interpreter, which has its
own interpretation of forward slashes. Apart from that, while forward
slashes are supported by Windows itself, they aren't the "standard"
separator, and may not be supported by other programs running on Windows.

In general, directory separators shouldn't occur within string
literals. Base directories should be taken from command-line parameters,
registry entries, configuration files, environment variables etc, not
embedded into the program. Paths relative to those directories should be
constructed with os.path.join().
 
E

Ethan Furman

Steven said:
BTW, Windows accepts / as well as \ as a path separator. You will have
far fewer headaches if you use that.

Just because Windows accepts / doesn't make it a good idea...

Python 2.5.4 (r254:67916, Dec 23 2008, 15:10:54) [MSC v.1310 32 bit
(Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
--> from glob import glob
--> print '\n'.join(glob('c:/temp/*'))
c:/temp\0C2O0007.TMP
c:/temp\27421
c:/temp\3K540007.TMP
c:/temp\AIF19780_01B_BACKUP.DBF
c:/temp\Arabic.bin
c:/temp\au-descriptor-1.6.0_23-b71.xml
c:/temp\AUCHECK_CORE.txt
c:/temp\AUCHECK_PARSER.txt
c:/temp\bar.py
c:/temp\bar.pyc
c:/temp\caller.py
c:/temp\caller.pyc
c:/temp\choose_python.pdf
c:/temp\CMD19639_B_BACKUP.DBF
c:/temp\COA.pdf
c:/temp\compress.py
c:/temp\compress.pyc
c:/temp\control.dbf
c:/temp\control.FPT

Or is there an option I'm missing so backslashes are not returned by
stdlib functions?

~Ethan~
 
S

Steven D'Aprano

Just because Windows accepts / doesn't make it a good idea...

No. Windows accepting slashes as the alternate path separator *enables*
you to use slash. What makes it a good idea is that you don't have to
worry about forgetting to escape backslashes:
C: emp
ile.txt


Nor do you have to care about the fact that raw strings are designed for
regular expressions, not Windows path names, and you can't have a raw
string ending in a single backslash:
File "<stdin>", line 1
location = r'C:\temp\'
^
SyntaxError: EOL while scanning string literal


The fact is that Windows' use of backslash as the path separator
conflicts with Python's use of backslashes. Since our code is written in
Python, trying to uses backslashes causes problems. One work-around is to
take advantage of the fact that Windows has an alternate separator
character, and use that. If you'd rather use raw strings, and special-
case backslashes at the end of paths, go right ahead.
--> from glob import glob
--> print '\n'.join(glob('c:/temp/*')) c:/temp\0C2O0007.TMP
c:/temp\27421
c:/temp\3K540007.TMP
[...]


Yes. Is there a problem? All those paths should be usable from Windows.
If you find it ugly to see paths with a mix of backslashes and forward
slashes, call os.path.normpath, or just do a simple string replace:

path = path.replace('/', '\\')

before displaying them to the user. Likewise if you have to pass the
paths to some application that doesn't understand slashes.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,012
Latest member
RoxanneDzm

Latest Threads

Top