Asked  7 Months ago    Answers:  5   Viewed   76 times

Given a path such as "mydir/myfile.txt", how do I find the file's absolute path relative to the current working directory in Python? E.g. on Windows, I might end up with:

"C:/example/cwd/mydir/myfile.txt"

 Answers

26
>>> import os
>>> os.path.abspath("mydir/myfile.txt")
'C:/example/cwd/mydir/myfile.txt'

Also works if it is already an absolute path:

>>> import os
>>> os.path.abspath("C:/example/cwd/mydir/myfile.txt")
'C:/example/cwd/mydir/myfile.txt'
Tuesday, June 1, 2021
 
TheLovelySausage
answered 7 Months ago
82

One potential issue to look out for is symbolic links. If DOCUMENT_ROOT contains a part that is a symlink, things will blow up (since realpath() will expand that symlink).

Of course, the solution might be as simple as wrapping $_SERVER['DOCUMENT_ROOT'] in realpath() as well.

Wednesday, March 31, 2021
 
Taptronic
answered 9 Months ago
44

You can use ctypes. According to the documentation on MSDN, GetShortPathName is in KERNEL32.DLL. Note that the real functions are GetShortPathNameW for wide (Unicode) characters and GetShortPathNameA for single-byte characters. Since wide characters are more general, we'll use that version. First, set the prototype according to the documentation:

import ctypes
from ctypes import wintypes
_GetShortPathNameW = ctypes.windll.kernel32.GetShortPathNameW
_GetShortPathNameW.argtypes = [wintypes.LPCWSTR, wintypes.LPWSTR, wintypes.DWORD]
_GetShortPathNameW.restype = wintypes.DWORD

GetShortPathName is used by first calling it without a destination buffer. It will return the number of characters you need to make the destination buffer. You then call it again with a buffer of that size. If, due to a TOCTTOU problem, the return value is still larger, keep trying until you've got it right. So:

def get_short_path_name(long_name):
    """
    Gets the short path name of a given long path.
    http://stackoverflow.com/a/23598461/200291
    """
    output_buf_size = 0
    while True:
        output_buf = ctypes.create_unicode_buffer(output_buf_size)
        needed = _GetShortPathNameW(long_name, output_buf, output_buf_size)
        if output_buf_size >= needed:
            return output_buf.value
        else:
            output_buf_size = needed
Monday, June 14, 2021
 
EastSw
answered 6 Months ago
26

The underlying operational system / shell reports real paths to python.

So, there really is no way around it, since os.getcwd() is a wrapped call to C Library getcwd() function.

There are some workarounds in the spirit of the one that you already know which is launching pwd.

Another one would involve using os.environ['PWD']. If that environmnent variable is set you can make some getcwd function that respects it.

The solution below combines both:

import os
from subprocess import Popen, PIPE

class CwdKeeper(object):
    def __init__(self):
        self._cwd = os.environ.get("PWD")
        if self._cwd is None: # no environment. fall back to calling pwd on shell
           self._cwd = Popen('pwd', stdout=PIPE).communicate()[0].strip()
        self._os_getcwd = os.getcwd
        self._os_chdir = os.chdir

    def chdir(self, path):
        if not self._cwd:
            return self._os_chdir(path)
        p = os.path.normpath(os.path.join(self._cwd, path))
        result = self._os_chdir(p)
        self._cwd = p
        os.environ["PWD"] = p
        return result

    def getcwd(self):
        if not self._cwd:
            return self._os_getcwd()
        return self._cwd

cwd = CwdKeeper()
print cwd.getcwd()
# use only cwd.chdir and cwd.getcwd from now on.    
# monkeypatch os if you want:
os.chdir = cwd.chdir
os.getcwd = cwd.getcwd
# now you can use os.chdir and os.getcwd as normal.
Friday, August 13, 2021
 
Student
answered 4 Months ago
87

It's the same as an absolute URL except that the schema will be the one used for the base URL. Thus, if you say //mysite.com/images/img.png on an https page, the image will be loaded with https and on an "ordinary" http page it will be loaded using the http schema (and, respectively, different default ports.)

This approach lets avoid the security warnings from browsers in the case when you have insecure content loaded by secure pages (and the pages can be loaded using both http and https protocols).

Sunday, August 15, 2021
 
Loui
answered 4 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :  
Share