How to get an absolute file path in Python

1,189,424

Solution 1

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

Solution 2

You could use the new Python 3.4 library pathlib. (You can also get it for Python 2.6 or 2.7 using pip install pathlib.) The authors wrote: "The aim of this library is to provide a simple hierarchy of classes to handle filesystem paths and the common operations users do over them."

To get an absolute path in Windows:

>>> from pathlib import Path
>>> p = Path("pythonw.exe").resolve()
>>> p
WindowsPath('C:/Python27/pythonw.exe')
>>> str(p)
'C:\\Python27\\pythonw.exe'

Or on UNIX:

>>> from pathlib import Path
>>> p = Path("python3.4").resolve()
>>> p
PosixPath('/opt/python3/bin/python3.4')
>>> str(p)
'/opt/python3/bin/python3.4'

Docs are here: https://docs.python.org/3/library/pathlib.html

Solution 3

import os
os.path.abspath(os.path.expanduser(os.path.expandvars(PathNameString)))

Note that expanduser is necessary (on Unix) in case the given expression for the file (or directory) name and location may contain a leading ~/(the tilde refers to the user's home directory), and expandvars takes care of any other environment variables (like $HOME).

Solution 4

Install a third-party path module (found on PyPI), it wraps all the os.path functions and other related functions into methods on an object that can be used wherever strings are used:

>>> from path import path
>>> path('mydir/myfile.txt').abspath()
'C:\\example\\cwd\\mydir\\myfile.txt'

Solution 5

Update for Python 3.4+ pathlib that actually answers the question:

from pathlib import Path

relative = Path("mydir/myfile.txt")
absolute = relative.absolute()  # absolute is a Path object

If you only need a temporary string, keep in mind that you can use Path objects with all the relevant functions in os.path, including of course abspath:

from os.path import abspath

absolute = abspath(relative)  # absolute is a str object
Share:
1,189,424
izb
Author by

izb

Twitter: http://twitter.com/izb

Updated on February 08, 2022

Comments

  • izb
    izb about 2 years

    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"
    
  • Torsten Marek
    Torsten Marek over 15 years
    Too bad they never got a proper filename abstraction module into the stdlib.
  • flow
    flow about 13 years
    @Torsten Marek: it's a sore and longstanding omission.
  • twasbrillig
    twasbrillig over 9 years
    They did now for Python 3.4: pathlib. See my answer in this thread.
  • coanor
    coanor over 9 years
    Note: On most platforms, this is equivalent to calling the function normpath() as follows: normpath(join(os.getcwd(), path)). So if mydir/myfile.txt do not under os.getcwd(), the absolute path is not the real path.
  • jpmc26
    jpmc26 over 9 years
    @coanor ? Without an explicit root, mydir/myfile.txt implicitly refers to a path inside the current working directory as is therefore equivalent to ./mydir/myfile.txt. That might not be the path you intended to input, but it seems like the correct interpretation of the path as far as I can tell. Could you elaborate?
  • NuclearPeon
    NuclearPeon over 8 years
    Very helpful. Using os.path.abspath() gave me an error: AttributeError: 'NoneType' object has no attribute 'startswith', using Path().resolve() does not with the same relative filepath. (Linux and Python3.4)
  • frakman1
    frakman1 almost 7 years
    There are yypos in this answer. It should be from path import Path then Path('mydir/myfile.txt').abspath()
  • Tom
    Tom almost 7 years
    There are no typos, you may have been using a different path module. The linked module uses a class named path.
  • Mike S
    Mike S over 5 years
    @jpmc26 I don't exactly follow coanor, but I would say that (contrary to what I presumed), there is no linkage between the argument to the abspath function and a real file. You could give any pathname- non-existent files and directory heirarchies are fine- and abspath will simply resolve the bits of the path (including the parent directory ".." element) and return a string. This is just a string computed from the current directory; any correlation to an actual file is accidental, it seems. Try os.path.abspath("/wow/junk/../blha/hooey"). It works.
  • jpmc26
    jpmc26 over 5 years
    @MikeS I'm honestly not sure why that would be unexpected behavior. It's absolute path, not absolute file or directory. If you want an existence check, call os.path.exists. To the contrary, systems like PowerShell that insist on the path existing with the standard path resolution function are a pain to use.
  • Mike S
    Mike S over 5 years
    @jpmc26 To assume that a path is just a string that looks like a pathname is not clear at all, and goes counter to how I've been thinking and speaking of pathnames for many years. I quote the Python 3 docs for abspath: "Return a normalized absolutized version of the pathname path." Not a"...version of the string path". A pathname, as defined by Posix, is "A string that is used to identify a file." The Python docs are explicit about relpath: "the filesystem is not accessed to confirm the existence or nature of path". If the argument here is obvious, why be explicit for relpath?
  • Mike S
    Mike S over 5 years
    @jpmc26 ...to further muddy the waters, the Python docs refer to abspath as "...equivalent to calling the function normpath() as follows: normpath(join(os.getcwd(), path))." which involves a system call, which is a reference to a real location in a filesystem. So again, we have a blending of the idea that "this refers to something (possibly) found on a filesystem" vs. "This is just a string. No identification with actual files (living or deceased) is intended or should be inferred." I think it would have been better to remove the reference to getcwd(), and follow relpath's example.
  • jpmc26
    jpmc26 over 5 years
    @MikeS os.getcwd() does not invoke a system call on the full path. It explicitly just fetches a string from current environment settings. Prepending its value is necessary when the path is relative, e.g. if it's './myfile.txt' or '../myfile.txt'. (Note that if path is absolute, then the entire result from getcwd() is completely discarded, even.) I can think of no reason why fetching part of the environment state would imply that the function involves checking if the complete path exists.
  • Mike S
    Mike S over 5 years
    @jpmc26 You are correct, but that's not what I'm claiming. Forget about getcwd if you must and reread my post. My point is: the documentation is inaccurate. They readily blend the concept of a pathname being a true pathname vs. it being nothing more than a string that might refer to a pathname in the filesystem. At other places in the documentation they take pains to point out the difference, because there is. Again, the definition of a pathname is not that it's a simple string. The argument to abspath is. This is my final comment; apologies for taking your time.
  • The Elemental of Destruction
    The Elemental of Destruction almost 5 years
    This is not what was being asked. They asked about a path in relation to the current working directory, which is not the same thing as the script directory, though they may sometimes end up having the same value.
  • Mond Wan
    Mond Wan almost 4 years
    According to my experiment, in window platform, resolve() returns full path to you only if it is able to resolve() file. But, os.path.abspath returns full path to you anyway even the file does not exists. However, in linux, it always return absolute path
  • aderchox
    aderchox over 3 years
    Why is that when the Path(__file__) alone (without the resolve method) is used in a module being imported along with a package, gives the absolute path instead of the relative path?
  • wim
    wim over 3 years
    Identical to the accepted answer, except it arrived 10 years late.
  • BallpointBen
    BallpointBen over 2 years
    Note that resolve() will follow symlinks. If you don't want this, use absolute() instead, which will leave not resolve symlinks.
  • Martin Thoma
    Martin Thoma over 2 years
    This answer was given with more detail already by Mad Physicist in 2018.
  • Florian Blume
    Florian Blume over 2 years
    I know this is a rather old answer, but isn't there one command that does all this in one call? Seems like this would be what would make the incoming path the most flexible and hence often needed (at least in my case that's true).
  • Marc Compere
    Marc Compere almost 2 years
    this will fail if the script is called from somewhere other than it's current location, for example from the parent folder.