57

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))
Lukas
  • 2,041
  • 2
  • 20
  • 29

3 Answers3

49

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.

Lukas
  • 2,041
  • 2
  • 20
  • 29
  • 2
    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. – William May 23 '20 at 16:28
19

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.

Yan QiDong
  • 2,744
  • 1
  • 18
  • 25
  • Yes, that is very nice indeed. I hope the Python community either accepts `pathlib.Path` anywhere or abandons it altogether. – Lukas Mar 01 '18 at 12:24
  • @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. – Jürgen A. Erhard Jul 30 '21 at 19:14
  • 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.* – Cecil Curry Nov 05 '21 at 05:23
1

If you don't mind using a third-party library:

$ pip install path

then:

from path import Path

with Path("somewhere"):
    # current working directory is now `somewhere`
    ...
# current working directory is restored to its original value. 

or if you want to do it without the context manager:

Path("somewhere").cd()
# current working directory is now changed to `somewhere`
AXO
  • 6,987
  • 4
  • 53
  • 56
  • 10
    Just to be perfectly clear, this is not the standard library pathlib. Using with pathlib.Path('x') does not change directory. – Jeremy Woodland Apr 09 '21 at 01:30