Bug or feature? Slash in os and os.path

Tim Peters tim_one at email.msn.com
Wed May 19 15:00:26 EDT 1999


[Christian Tismer]
> What is the desired behavior of os.listdir, os.path.listdir
> and os.path.exists?
>
> I wouldn't care if appending a slash is allowed or not,
> but it should always be consistent.
>
> >>> os.path.exists('D:/Back/RsServer/gm/xmls/gm/cicos/') # oops
> 0
> >>> os.path.exists('D:/Back/RsServer/gm/xmls/gm/cicos') # ok
> 1
> >>> os.path.isdir('D:/Back/RsServer/gm/xmls/gm/cicos/') # oops
> 0
> >>> os.path.isdir('D:/Back/RsServer/gm/xmls/gm/cicos') # ok
> 1
>
> >>> os.listdir('D:/Back/RsServer/gm/xmls/gm') # ok
> ['subsets', 'cicos', ...]
>
> >>> os.listdir('D:/Back/RsServer/gm/xmls/gm/') # ok
> ['subsets', 'cicos', ...]
> >>>

Yes, it sucks, but I don't know how to fix it.  The behaviors of exists,
isdir and isfile are inherited from os.stat, and Microsoft's implementation
of the latter is what's picky about the trailing slash.  Play with this:

#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>

static void
check(const char* path)
{
    struct _stat buf;
    int result = _stat(path, &buf);
    printf("%s ", path);
    if (result)
        printf("doesn't exist; code %d", result);
    else
        printf("exists");
    printf(".\n");
}

void main()
{
    check("d:/python");
    check("d:/python/");
    check("d:/python/python.exe");
    check("d:/python/python.exe/");
    check("d:");
    check("d:/");
}

The first 4 lines for me are (Win95):

d:/python exists.
d:/python/ doesn't exist; code -1.
d:/python/python.exe exists.
d:/python/python.exe/ doesn't exist; code -1.

Python returns the same, because the above is what libc is telling it.  So
you're tempted to conclude "ok, under Windows, never ever put a trailing
slash on the argument".  But then the output of the last two lines:

d: doesn't exist; code -1.
d:/ exists.

So sometimes you *have* to use a trailing slash!  Brrrrrr.  Consistency is
impossible.

Believe UNC mount points (like \\machine\share\) act similarly to raw drive
letters here, requiring a trailing slash to succeed.

OTOH, the native Win32 GetFileAttributes works fine:

static void
check(const char* path)
{
    DWORD result = GetFileAttributes(path);
    printf("%s ", path);
    if (result != 0xffffffff)
        printf("exists");
    else
        printf("doesn't exist");
    printf(".\n");

}

That prints:

d:/python exists.
d:/python/ exists.
d:/python/python.exe exists.
d:/python/python.exe/ doesn't exist.
d: exists.
d:/ exists.

the-first-known-lame-implementation-of-libc<wink>-ly y'rs  - tim






More information about the Python-list mailing list