3

I have a script, B.py, that is imported from another script, say A.py

If I import B in A, the __file__ magical constant, has converted some uppercase letters in its path to lowercase.

If I run B file directly, the __file__ constant HAS proper case regarding the path.

In short this is what happens. The following:

telplugins_path = os.path.dirname(os.path.realpath(__file__))

give me a path like this

C:\\Python\\lib\\site_packages\\mypackage

when it should be

C:\\Python\\Lib\\site_packages\\mypackage

Observe the change on 'Lib' -> 'lib'

Anyone have an idea on how to get the path to __file__ with proper case? Running this on Windows.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
Totte Karlsson
  • 1,261
  • 1
  • 20
  • 55

4 Answers4

3

The windows file system is case-insensitive.

Python is just configured with the C:\Python\lib\site_packages path in the sys.path search list, so when you import your module, python constructs the filepath with the lowercase version.

This is not a problem. Windows will continue to load files using the lowercased version of the path.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • 1
    This is a problem for me. The path is handed to lower level C++ module that checks if the folder exists. Since it has the wrong case, it comes back saying it does not exist! I need a solution that gives the proper path, with proper case. Your answer don't provide that, and therefore is no proper answer. – Totte Karlsson Jan 16 '14 at 22:22
  • 1
    @TotteKarlsson: Then that C++ module uses the wrong API to test for folder existence! – Martijn Pieters Jan 16 '14 at 22:23
  • 1
    @TotteKarlsson: Python has the [`os.path.normcase()` function](http://docs.python.org/2/library/os.path.html#os.path.normcase) which would *lowercase* the path, including the initial `P` for `Python`, which may leave you of worse. – Martijn Pieters Jan 16 '14 at 22:24
  • @TotteKarlsson: for the C++ folder check, see [How do you check if a directory exists on Windows in C?](http://stackoverflow.com/q/6218325) for the proper method to test if a folder exists. – Martijn Pieters Jan 16 '14 at 22:27
  • 2
    OBSERVE: The question is how to get a path with proper case. I do appreciate suggestions about other programming techniques. However, the main question is, again, how to get the path with a proper case? – Totte Karlsson Jan 16 '14 at 22:50
  • The underlying C++ code handling the path is Poco. Poco do have a flag using caseless or not. Setting that solved the problem. However, even though you can't have two folders with the same name in windows, but different case, does not mean the foldernames lack "caseness". Anyway, thanks for your response. – Totte Karlsson Jan 17 '14 at 01:00
  • I didn't say the path was caseless, just that Windows treats all file operations as case insensitive. This is why Python includes a `os.path.normcase()` method as well, to make handling (comparing, hashing, etc.) Windows file paths more manageable. Note that Windows also supports using `/` instead of ``\`` as path separator (interchangeably). Fun! – Martijn Pieters Jan 17 '14 at 01:14
2

On windows, the win32 module contain the function GetLongPathName. It does solve the above problem.

That is, the following gives a path with correct case:

aFile = win32api.GetLongPathName(__file__)
pathWithCorrectCase = os.path.split(aFile)[0]

However, I would like to avoid using the win32 module, since it seem not totally "standard".

Totte Karlsson
  • 1,261
  • 1
  • 20
  • 55
0

Yields via standard library:

cased_path = glob.glob(re.sub(r'([^:])(?=[/\\]|$)', r'[\1]', __file__))[0]
kxr
  • 4,841
  • 1
  • 49
  • 32
0

There are certain calls you can make on windows that do fail with improper casing. There are also scenarios such as mine where these calls are being sent to a machiine that IS case sensitive.

Whatever the case may be, if you need proper casing on windows this is the best solution i have found.

For individual files, its easy enough to listdir, but if you have a directory path that you are not positive is properly cased:

import win32com.client as com
_dir = <your path>
fso = com.Dispat("Scripting.FileSystemObject")
folder = fso.GetFolder(_dir)
path = folder.path

This will return the properly cased path.

aescript
  • 1,775
  • 4
  • 20
  • 30