Как мне изменить каталог обратно в исходный рабочий каталог с Python?

У меня есть функция, которая похожа на приведенную ниже. Я не уверен, как использовать модуль os, чтобы вернуться к исходному рабочему каталогу после завершения выполнения jar.

def run(): 
    owd = os.getcwd()
    #first change dir to build_dir path
    os.chdir(testDir)
    #run jar from test directory
    os.system(cmd)
    #change dir back to original working directory (owd)

примечание: я думаю, что мое форматирование кода выключено - не знаю почему. Мои извинения заранее

8 ответов

Решение

Вам просто нужно добавить строку:

os.chdir(owd)

Просто примечание, на которое также был дан ответ на ваш другой вопрос.

Менеджер контекста является очень подходящим инструментом для этой работы:

from contextlib import contextmanager

@contextmanager
def cwd(path):
    oldpwd=os.getcwd()
    os.chdir(path)
    try:
        yield
    finally:
        os.chdir(oldpwd)

...используется в качестве:

os.chdir('/tmp') # for testing purposes, be in a known directory
print 'before context manager: %s' % os.getcwd()
with cwd('/'):
    # code inside this block, and only inside this block, is in the new directory
    print 'inside context manager: %s' % os.getcwd()
print 'after context manager: %s' % os.getcwd()

... который даст что-то вроде:

before context manager: /tmp
inside context manager: /
after context manager: /tmp

Это на самом деле превосходит cd - встроенная оболочка, поскольку она также заботится о смене каталогов обратно при выходе из блока из-за создаваемого исключения.


Для вашего конкретного случая использования это будет:

with cwd(testDir):
    os.system(cmd)

Другой вариант для рассмотрения - использование subprocess.call() вместо os.system(), который позволит вам указать рабочий каталог для запуска команды:

# note: better to modify this to not need shell=True if possible
subprocess.call(cmd, cwd=testDir, shell=True)

... что помешает вам вообще менять каталог переводчика.

Совет использовать os.chdir(owd) это хорошо. Было бы целесообразно поместить код, которому требуется измененный каталог, в try:finally блок (или в Python 2.6 и позже, with: блок.) Это снижает риск того, что вы случайно поставите return в коде до изменения обратно в исходный каталог.

def run(): 
    owd = os.getcwd()
    try:
        #first change dir to build_dir path
        os.chdir(testDir)
        #run jar from test directory
        os.system(cmd)
    finally:
        #change dir back to original working directory (owd)
        os.chdir(owd)

Обновление Python 3.11:

Теперь вы можете просто использоватьcontextlib.chdirиз стандартной библиотеки. Он меняет директорию при входе в блок, потом восстанавливает старую директорию обратно:

      from contextlib import chdir
from os import getcwd

print(f"Before: {getcwd()}")
with chdir("/"):
    print(f"inside: {getcwd()}")
print(f"after: {getcwd()}")

Контекстного менеджера для этой ситуации (выполнение системной команды) излишне. Лучшее решение - использовать subprocess модуль вместо этого (Python 2.4 и выше) и run или же popen методы с cwd аргумент.

Итак, ваш код можно заменить на:

def run(): 
    #run jar from test directory
    subprocess.run(cmd, cwd=testDir)

См. https://bugs.python.org/issue25625 и https://docs.python.org/3/library/subprocess.html#subprocess-replacements.

os.chdir(owd) должен добиться цели (как вы сделали, когда переходили на testDir)

Python чувствителен к регистру, поэтому при вводе пути убедитесь, что он совпадает с каталогом, который вы хотите установить.

import os

os.getcwd()

os.chdir('C:\\')

Я просмотрел ответы на StackOverflow и в конце концов решил написать для этой цели собственный декоратор:

      from collections.abc import Callable
from functools import wraps
from typing import ParamSpec, TypeVar


T = TypeVar('T')
P = ParamSpec('P')
    
    
def enter_subdir(subdir: str) -> Callable[[Callable[P, T]], Callable[P, T]]:
    """During the execution of a function, temporarily enter a subdirectory."""

    def decorator(function: Callable[P, T]) -> Callable[P, T]:
        @wraps(function)
        def wrapper(*args, **kwargs) -> T:
            os.makedirs(subdir, exist_ok=True)
            os.chdir(subdir)
            result = function(*args, **kwargs)
            os.chdir("..")
            return result

        return wrapper

    return decorator
Другие вопросы по тегам