Each Answer to this Q is separated by one/two green lines.
I have following code:
directory = r'D:\images' for file in os.listdir(directory): print(os.path.abspath(file))
and I want next output:
- D:\images\img2.jpg and so on
But I get different result:
where D:\code is my current working directory and this result is the same as
So, the question is: What is the purpose of os.path.abspath while I must use
to get REAL absolute path of my file? Show real use-cases if possible.
The problem is with your understanding of
os.listdir() returns the names of each of the files in the directory. This will give you:
img1.jpg img2.jpg ...
When you pass these to
os.path.abspath(), they are seen as relative paths. This means it is relative to the directory from where you are executing your code. This is why you get “D:\code\img1.jpg”.
Instead, what you want to do is join the file names with the directory path you are listing.
listdir produces the file names in a directory, with no reference to the name of the directory itself. Without any other information,
abspath can only form an absolute path from the only directory it can know about: the current working directory. You can always change the working directory before your loop:
os.chdir(directory) for f in os.listdir('.'): print(os.path.abspath(f))
os.path functions are pretty low-level. Iterating through a directory (or a series of descending directories) requires your program to assemble file paths manually. It can be convenient to define a utility function that generates the paths you’re going to need just once, so that path assembly logic doesn’t have to be repeated in every directory iteration. For example:
import os def better_listdir(dirpath): """ Generator yielding (filename, filepath) tuples for every file in the given directory path. """ # First clean up dirpath to absolutize relative paths and # symbolic path names (e.g. `.`, `..`, and `~`) dirpath = os.path.abspath(os.path.expanduser(dirpath)) # List out (filename, filepath) tuples for filename in os.listdir(dirpath): yield (filename, os.path.join(dirpath, filename)) if __name__ == '__main__': for fname, fpath in better_listdir('~'): print fname, '->', fpath
Alternatively, there are “higher level” path modules that one can employ, such as py.path, path.py, and pathlib (now a standard part of Python, for version 3.4 and above, but available for 2.7 forward). Those add dependencies to your project, but up-level many aspects of file, filename, and filepath handling.