Как мне изменить каталог обратно в исходный рабочий каталог с 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