os.path.join doubt

Discussion in 'Python' started by harryos, Feb 3, 2011.

  1. harryos

    harryos Guest

    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
     
    harryos, Feb 3, 2011
    #1
    1. Advertising

  2. harryos

    Chris Rebert Guest

    On Wed, Feb 2, 2011 at 8:46 PM, harryos <> wrote:
    > 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
    --
    http://blog.rebertia.com
     
    Chris Rebert, Feb 3, 2011
    #2
    1. Advertising

  3. On Wed, 02 Feb 2011 20:46:12 -0800, harryos wrote:

    > 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:


    >>> os.path.normpath('x/y/../z')

    '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.



    --
    Steven
     
    Steven D'Aprano, Feb 3, 2011
    #3
  4. harryos

    Nobody Guest

    On Thu, 03 Feb 2011 06:31:49 +0000, Steven D'Aprano wrote:

    > On Wed, 02 Feb 2011 20:46:12 -0800, harryos wrote:
    >
    >> In windows ,I tried this
    >>
    >> p1 = "C:\Users\me\Documents"
    >> p2 = "..\Pictures\images\my.jpg"


    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().
     
    Nobody, Feb 3, 2011
    #4
  5. harryos

    Ethan Furman Guest

    Steven D'Aprano wrote:
    > 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~
     
    Ethan Furman, Feb 3, 2011
    #5
  6. On Thu, 03 Feb 2011 07:58:55 -0800, Ethan Furman wrote:

    > Steven D'Aprano wrote:
    >> 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...


    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:

    >>> print("C:\temp\file.txt")

    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:

    >>> location = r'C:\temp\' # Path ending in a 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.


    --
    Steven
     
    Steven D'Aprano, Feb 3, 2011
    #6
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Alan Silver
    Replies:
    0
    Views:
    917
    Alan Silver
    Jun 5, 2006
  2. googleboy
    Replies:
    1
    Views:
    956
    Benji York
    Oct 1, 2005
  3. Steve
    Replies:
    1
    Views:
    1,007
    Fredrik Lundh
    Dec 13, 2005
  4. Bob Nelson

    doubt about doubt

    Bob Nelson, Jul 28, 2006, in forum: C Programming
    Replies:
    11
    Views:
    661
  5. Replies:
    0
    Views:
    593
Loading...

Share This Page