77

What is the intended way to change directory using the Python pathlib (Documentation) functionality?

Lets assume I create a Path object as follows:

from pathlib import Path
path = Path('/etc')

Currently I just know the following, but that seems to undermine the idea of pathlib.

import os
os.chdir(str(path))
7
  • changing the current directory is rarely a good idea anyway. Why do you need to change directory for? Commented Jan 19, 2017 at 12:58
  • There is a small bash script I want to rewrite in Python. That way I can handle errors more easily than calling an external bash script. Commented Jan 19, 2017 at 13:41
  • 1
    you don't have to use pathlib if you don't need it - os.chdir('/etc') Commented Jan 19, 2017 at 14:48
  • I feel like pathlib leads to more elegant code. But since cd is not elegant by any means, I might as well go with os.chdir('/etc')? Commented Jan 19, 2017 at 14:54
  • 3
    @furas; tell that to the core devs. See Path.read_bytes and Path.read_text. Commented Jul 30, 2021 at 19:11

2 Answers 2

69

Based on the comments I realized that pathlib does not help changing directories and that directory changes should be avoided if possible.

Since I needed to call bash scripts outside of Python from the correct directory, I opted for using a context manager for a cleaner way of changing directories similar to this answer:

import os
import contextlib
from pathlib import Path

@contextlib.contextmanager
def working_directory(path):
    """Changes working directory and returns to previous on exit."""
    prev_cwd = Path.cwd()
    os.chdir(path)
    try:
        yield
    finally:
        os.chdir(prev_cwd)

A good alternative is to use the cwd parameter of the subprocess.Popen class as in this answer.

If you are using Python <3.6 and path is actually a pathlib.Path, you need str(path) in the chdir statements.

Sign up to request clarification or add additional context in comments.

1 Comment

This is exactly what I needed! I'm testing a command line tool whose required parameters depend on the cwd, so I need to move the cwd around in order to test this functionality. However if I write it the naive way, then when a test fails it will throw an unexpected exception and the cwd doesn't get moved back, meaning that all future tests start with the wrong cwd and give useless errors. Using a context manager means I know it gets moved back! I think try-except-finally blocks are also valid, but writing a context manager is more reliable and saves code over multiple tests.
30

In the Python 3.6 or above, os.chdir() can deal with Path object directly. In fact, the Path object can replace most str paths in standard libraries.

os.chdir(path) Change the current working directory to path.

This function can support specifying a file descriptor. The descriptor must refer to an opened directory, not an open file.

New in version 3.3: Added support for specifying path as a file descriptor on some platforms.

Changed in version 3.6: Accepts a path-like object.

import os
from pathlib import Path

path = Path('/etc')
os.chdir(path)

This may help in the future projects which do not have to be compatible with 3.5 or below.

3 Comments

Yes, that is very nice indeed. I hope the Python community either accepts pathlib.Path anywhere or abandons it altogether.
@Lukas: I really want to like it, but currently I can't accept it. And since it's been three years since your comment, I suspect I can't ever… and os.path will stay anyway. I could and would accept it if it could replace os.path completely. Therein lies the rub. For me at least.
Naturally, this should be the accepted answer. Yes, it'd be preferable for API orthogonality if a hypothetical full-fledged pathlib.Path.chdir() method existed – but this is the next best thing. Let's not let the perfect become the enemy of the good yet again.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.