6

I need to perform an action without changing the global working directory. My case is I have a few folders, and in each, there are a few files. I need to do some computations using those files. Initially, I tried the following:

with os.chdir('/directory'):
    ...some code needing execution inside 

but got AttributeError: __enter__. After reading up online using with seems not to be an option. Therefore I'm looking to find another elegant way of doing so.

I also tried just using os statements like so:

cwd = os.getcwd()

os.chdir('/directory')
..run code inside directory 

os.chdir(cwd)

but this is a pain during debugging and seems like a bad practice.

5
  • Why do you need to switch the working directory? Are you calling an external program which needs to be started in the specific folder? Commented Jan 8, 2023 at 15:32
  • os.chdir returns None, which is not a context manager. That doesn't mean you can't find or write an appropriate context manager. Commented Jan 8, 2023 at 15:36
  • In a nutshell yes, I need to do a specific action within some directory and then continue the program in a working directory, I found an approach using straight os statements to be very convoluted @phibel Commented Jan 8, 2023 at 15:38
  • 1
    There is a contextlib.chdir in Python 3.11. If you are using an earlier version, you can also refer to its source code. Commented Jan 8, 2023 at 15:41
  • @sage When you are calling an external program, you could use subprocess which has a cwd argument: stackoverflow.com/questions/21406887/… Commented Jan 8, 2023 at 15:44

3 Answers 3

6

You can write your own context manager to temporarily change the working directory.

import contextlib


@contextlib.contextmanager
def new_cd(x):
    d = os.getcwd()

    # This could raise an exception, but it's probably
    # best to let it propagate and let the caller
    # deal with it, since they requested x
    os.chdir(x)

    try:
        yield

    finally:
        # This could also raise an exception, but you *really*
        # aren't equipped to figure out what went wrong if the
        # old working directory can't be restored.
        os.chdir(d)


with new_cd('/directory'):
    ...
Sign up to request clarification or add additional context in comments.

2 Comments

Is it beneficial to include try: and finally: here?
Probably. Even if there's an uncaught exception in the body of the with statement, it would be a good idea to try to restore the original working directory before re-raising it.
5

You can make your own context manager. This answer is similar @chepner 's, but will still change back the current working directory in case of error.

import contextlib
import os

@contextlib.contextmanager
#temporarily change to a different working directory
def temporaryWorkingDirectory(path):
    _oldCWD = os.getcwd()
    os.chdir(os.path.abspath(path))

    try:
        yield
    finally:
        os.chdir(_oldCWD)

I tested it using this

#test
print(os.getcwd())
with temporaryWorkingDirectory("../"):
    print(os.getcwd())
print(os.getcwd())

4 Comments

Isn't this exactly the same as chepner's answer, not "similar to it"?
@Chris Note that chepner's answer was edited after the release of this answer.
@MechanicPig, only to add the try and finally. I don't think this answer is meaningfully different from chepner's original or current answer.
They posted a few seconds earlier than me or something. Since I had the try finally which may be beneficial, I went ahead and posted anyways.
3

Consider spawning a subprocess:

import subprocess

subprocess.run(cmd, cwd="/directory")

See https://docs.python.org/3/library/subprocess.html.

1 Comment

The interesting thing about this call is that run() does not change directory until after the shell is spawned - for example, in windows + cygwin, you will almost always get CMD.EXE was started with the above path as the current directory. UNC paths are not supported. Defaulting to Windows directory. C:\Windows

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.