Python file, directory, and path

You can get the file content as a list by [1] opening the file in the with statement and [2] using the readlines() method.

with open('a.txt') as f:
    s = f.readlines()

print(s)  # ['C\n', 'C++\n', 'Java\n', 'Python']

a.txt

C
C++
Java
Python

The readlines() of a Python file object (precisely "TextIOWrapper") reads the content and returns the list of string lines. This method seems very useful but each element ends with a newline. If you don't need trailing newlines, read() method is better.

with open('a.txt') as f:
    c = f.read()
    s = c.splitlines()

print(c)
# C
# C++
# Java
# Python

print(s)  # ['C', 'C++', 'Java', 'Python']

The read() returns the content as a string. The splitlines() splits a string by a newline.

Use of pathlib

from pathlib import Path

p = Path('a.txt')
c = p.read_text()
s = c.splitlines()

print(c)
# C
# C++
# Java
# Python

print(s)  # ['C', 'C++', 'Java', 'Python']

The read_text() of a Path object, which is instantiated with the specified path, returns the file content without the with statement. It opens and closes a file. It can be used from Python 3.5.

read_text()

Python Path.read_text function can substitute the traditional with-open way.

from pathlib import Path

p = Path(__file__).parent / 'data' / 'a.html'
c = p.read_text()

print(p.as_posix())
# /Users/serif/python/test/data/a.html

print(c)
'''
<!DOCTYPE html>
<html lang="en">
<head><title>Title</title></head>
<body></body>
</html>
'''

p is a PosixPath object representing the path of a.html. Once you get the path object, you can read the content without with statement.

read_text is very useful and supported from Python 3.5. Avoid writing with-open-read code only to read files.

Write a text in a file

From Python 3.5, we can write a file with Path.

from pathlib import Path

p = Path(__file__).parent / 'data' / 'mail.txt'

mail = 'Hello'

p.write_text(mail)

First, get the path of a file you want to write. Second, use write_text function. That's all.

After running the above code, hello is written in mail.txt.

If the file already exists, the content will be overwritten. And surprisingly, if the file doesn't exist, the file will be automatically created and written.

Get the file name

The Python Path class has name, stem and suffix properties representing the filename, filename without extension and extension respectively.

from pathlib import Path

p = Path('a.html')

name = p.name
stem = p.stem
suffix = p.suffix

print(name)  # a.html
print(stem)  # a
print(suffix)  # .html

Note that Path is derived from PurePath. Precisely, those properties are PurePath ones. The Path object can take the relative path as follows.

from pathlib import Path

p = Path('../util/example.py')

name = p.name
stem = p.stem
suffix = p.suffix

print(name)  # example.py
print(stem)  # example
print(suffix)  # .py

No problem if the file doesn't exist

from pathlib import Path

p = Path('b.html')

name = p.name
stem = p.stem
suffix = p.suffix

print(name)  # b.html
print(stem)  # b
print(suffix)  # .html

b.html doesn't exist in the current directory but the Path object has properties name, stem and suffix. In that case, Python doesn't create b.html.

Extract the filename from an absolute path

from pathlib import Path

p = Path('/Users/serif/python/test/files/a.html')
name = p.name

print(name)  # a.html

The Path class can be instantiated with an absolute path.

Using os module

import os

p = os.path.abspath('a.html')

print(p)  # /Users/serif/python/test/files/a.html

b = os.path.basename(p)

print(b)  # a.html

You can extract the filename from the given absolute path using os module.

Get the suffix of a file.

from pathlib import Path

p1 = Path(__file__)

print(p1.as_posix())
# /Users/serif/python/test/zip.py

f1 = p1.name
s1 = p1.suffix

print(f1)  # zip.py
print(s1)  # .py

Before using Path, pathlib must be imported. p1 is a PosixPath object representing the current file. It has the suffix property, which starts with . (dot).

from pathlib import Path

p1 = Path(__file__)
p2 = Path(__file__).parent
p3 = Path(__file__).parent / 'data' / 'b'

print(p1.as_posix())
# /Users/serif/python/test/zip.py

print(p2.as_posix())
# /Users/serif/python/test

print(p3.as_posix())
# /Users/serif/python/test/data/b


s1 = p1.suffix
s2 = p2.suffix
s3 = p3.suffix

print(s1)  # .py
print(s2)  #
print(s3)  #

p2 represents the current directory and its suffix is empty. p3 is the path of b and this filename doesn't contain suffix. So p3.suffix is empty.

Get the file size in Python:

import os
from pathlib import Path

f = Path(__file__)

print(f.as_posix())  # /Users/serif/python/test/main.py

st_size = f.stat().st_size
size = os.path.getsize(__file__)

print(st_size)  # 215
print(size)  # 215

There are two solutions:

  • importing os and using os.path.getsize()
  • importing Path and using stat().st_size

Since Python 3.4, pathlib has been very useful module handling the filesystem. The stat() returns the os.stat_result object that has the information of file size, created time, permission, etc. Some of them depends on OS.

Get all the files and directories of the current directory in Python

from pathlib import Path

# current file
file = Path(__file__)
print(file)  # /Users/serif/python/test/main.py
print(type(file))  # <class 'pathlib.PosixPath'>

# current directory
parent = Path(__file__).parent
print(parent)  # /Users/serif/python/test

# items in parent
items = parent.iterdir()

for item in items:
    print(item)

# /Users/serif/python/test/util
# /Users/serif/python/test/game.py
# /Users/serif/python/test/__pycache__
# /Users/serif/python/test/main.py
# /Users/serif/python/test/.idea

First, import Path from pathlib and get the PosixPath object of the current directory. __file__ is the current file path.

The iterdir() returns the items in a directory. Each is actually a PosixPath object representing the path of a file or directory.

Get only directories in the current directory

from pathlib import Path

parent = Path(__file__).parent
items = parent.iterdir()

for item in items:
    if item.is_dir():
        print(item.as_posix())

# /Users/serif/python/test/util
# /Users/serif/python/test/__pycache__
# /Users/serif/python/test/.idea

The is_dir() checks if the path is a directory.

Get only files in the current directory

from pathlib import Path

parent = Path(__file__).parent
items = parent.iterdir()

for item in items:
    if item.is_file():
        print(item.as_posix())

# /Users/serif/python/test/game.py
# /Users/serif/python/test/main.py

The is_file() checks if the path is a file.

Get an absolute path

from pathlib import Path

p = Path(__file__)

p1 = p.as_posix()
p2 = p.absolute()

print(p1)  # /Users/serif/python/test/main.py
print(p2)  # /Users/serif/python/test/main.py

The as_posix() and absolute() returns the absolute path.

Path.resolve()

Python Path.resolve returns the absolute path of a file/directory.

from pathlib import Path

p1 = Path()
print(p1.resolve())
# /Users/serif/python/test

p2 = Path(__file__)
print(p2.resolve())
# /Users/serif/python/test/zip.py

p3 = Path('.')
print(p3.resolve())
# /Users/serif/python/test

p4 = Path('./')
print(p4.resolve())
# /Users/serif/python/test

p5 = Path('..')
print(p5.resolve())
# /Users/serif/python

p6 = Path('../')
print(p6.resolve())
# /Users/serif/python

p1-p6 are all the PosixPath objects. PosixPath has useful methods and properties and resolve returns the absolute path.

p1 is the current directory and p2 is the current file. p1, p3, p4 are all the same.

  • Path() -> dir
  • Path(file) -> file

Python pathlib is useful for path-handling and almost substitute os.path module.

Create a file in Python

Path class has touch method that creates a file. Path is in pathlib module and useful to handle files and directories in Python.

from pathlib import Path

p = Path(__file__).parent / 'data' / 'mail.txt'

p.touch()

touch creates a file if the path doesn't exist. If the path already exists, Python do nothing. In that case, the file is not overwritten to empty content by touch. touch doesn't change the file content.

If you want to create a file or overwrite, use write_text. This method overwrites or creates if the file doesn't exist.

More: Delete a file

Delete a file in Python

You can easily delete a file using pathlib.

from pathlib import Path

p = Path(__file__).parent / 'data' / 'mail.txt'

p.unlink()

First, get the path of a file you want to delete. Second, use unlink function. After running the code, the file is removed.

If the file doesn't exist, Python raises the FileNotFoundError exception.

FileNotFoundError: [Errno 2] No such file or directory: '/Users/serif/python/test/data/mail.txt'

From Python 3.8, missing_ok option was added. If missing_ok is True, the FileNotFoundError exception is raised when the file doesn't exist.

from pathlib import Path

p = Path(__file__).parent / 'data' / 'mail.txt'

p.unlink(missing_ok=True)

The default of missing_ok is False.

Python File

Python Tutorial