При использовании этого метода необходимо следовать двум рекомендациям:
Перехватите исключение (WindowsError, OSError) по неверному пути. Если выдается исключение, не выполняйте никаких рекурсивных операций, особенно деструктивных. Они будут действовать по старому пути, а не по новому.
Вернитесь в старый каталог, когда закончите. Это можно сделать безопасным для исключения способом, заключив ваш вызов chdir в менеджер контекста, как это сделал Брайан М. Хант в своем ответе .
Изменение текущего рабочего каталога в подпроцессе не приводит к изменению текущего рабочего каталога в родительском процессе. Это верно и для интерпретатора Python. Вы не можете использовать os.chdir()для изменения CWD вызывающего процесса.
Легкий ответ cdunn2001 на основе декоратора - идеальный подход для современного Python. Приведенный выше ответ демонстрирует почему. Никогда не звоните os.chdir()вне контекстного менеджера, если только вы не думаете, что знаете, что делаете. ( Вы, вероятно, не. )
Сесил Карри
6
Это самый простой способ в интерактивной оболочке, я думаю. Обратите внимание, что в Windows вы должны использовать прямую косую черту, какos.chdir("C:/path/to/location")
Josiah
Следует помнить одну вещь: если вы сделаете вашу программу на python исполняемой и запустите ее в cron, она запустится в вашем домашнем каталоге. Поэтому лучше всего использовать полный путь. Это определенно работает, но я все еще использую полные пути в любом скрипте, который я могу вызвать из Python, потому что нет гарантии, что это будет применяться за пределами самой программы Python.
SDsolar
311
Вот пример контекстного менеджера для изменения рабочего каталога. Это проще, чем версия ActiveState, о которой говорится в другом месте, но это делает работу.
Диспетчер контекста: cd
import osclass cd:"""Context manager for changing the current working directory"""def __init__(self, newPath):
self.newPath = os.path.expanduser(newPath)def __enter__(self):
self.savedPath = os.getcwd()
os.chdir(self.newPath)def __exit__(self, etype, value, traceback):
os.chdir(self.savedPath)
import subprocess # just to call an arbitrary command e.g. 'ls'# enter the directory like this:with cd("~/Library"):# we are in ~/Library
subprocess.call("ls")# outside the context manager we are back wherever we started.
Если вам когда-нибудь понадобится узнать, из какого каталога вы изменили, вы можете просто добавить return selfв конце __enter__. Таким образом, вы можете сделать with cd('foo') as cm:и получить доступ к предыдущему каталогу, какcm.savedPath
Сэм Ф
Обратите внимание, что есть случаи, когда возврат к старому каталогу (тот, который хранится в «сохраненном пути») невозможен. Например, если более привилегированный процесс запускает менее привилегированный процесс, второй процесс наследует рабочий каталог первого процесса, даже в тех случаях, когда второй процесс не может войти в этот рабочий каталог со своими собственными возможностями.
Кай Петцке
141
Я бы использовал os.chdirтак:
os.chdir("/path/to/change/to")
Кстати, если вам нужно выяснить ваш текущий путь, используйте os.getcwd().
Brilliance! Если бы вводный комментарий из принятого ответа был введен в этот ответ, это было бы неизмеримо идеальным. Тем не менее, этот ответ лаконичен, Python-безопасная реализация гарантирует все положительные отзывы, которые я должен дать.
Сесил Карри
3
Почему yieldи нет return? Это должен быть генератор?
EKons
Пожалуйста, прокомментируйте актуальность доходности против возврата!
NicoBerrogorry
1
@NicoBerrogorry, это генератор. Смотрите документы на contextlib.contextmanager . Это очень полезный шаблон в Python, который стоит изучить.
cdunn2001
25
Если вы используете относительно новую версию Python, вы также можете использовать менеджер контекста, такой как этот :
from __future__ import with_statementfrom grizzled.os import working_directorywith working_directory(path_to_directory):# code in here occurs within the directory# code here is in the original directory
Зависимости плохие. Встроенный в Python contextlib.contextmanagerдекоратор хорош. Смотрите ответ cdunn2001 на основе декоратора , который в идеале был бы принятым ответом сейчас.
Сесил Карри
14
Как уже указывалось другими, все решения, приведенные выше, меняют только рабочий каталог текущего процесса. Это теряется при выходе из оболочки Unix. Если вы в отчаянии, вы можете изменить каталог родительской оболочки в Unix с помощью этого ужасного хака:
def quote_against_shell_expansion(s):import pipesreturn pipes.quote(s)def put_text_back_into_terminal_input_buffer(text):# use of this means that it only works in an interactive session# (and if the user types while it runs they could insert characters between the characters in 'text'!)import fcntl, termiosfor c in text:
fcntl.ioctl(1, termios.TIOCSTI, c)def change_parent_process_directory(dest):# the horror
put_text_back_into_terminal_input_buffer("cd "+quote_against_shell_expansion(dest)+"\n")
Безумный, хрупкий взлом получает обязательные откаты. Никто никогда не должен делать это, особенно с этим "и если пользователь печатает, пока он работает ...", будьте осторожны. Тем не менее, это щекочет повстанческой neckbeard во мне , чтобы увидеть , что изменение родительского УХА является родом-но на самом деле не представляется возможным. Upvotes! Upvotes для всех!
import os
abs_path ='C://a/b/c'
rel_path ='./folder'
os.chdir(abs_path)
os.chdir(rel_path)
Вы можете использовать оба с os.chdir (abs_path) или os.chdir (rel_path), нет необходимости вызывать os.getcwd (), чтобы использовать относительный путь.
Если вы используете spyder и love GUI, вы можете просто нажать на кнопку папки в верхнем правом углу экрана и перемещаться по папкам / каталогам, которые вы хотите использовать в качестве текущего каталога. После этого вы можете перейти на вкладку «Обозреватель файлов» окна в IDE spyder и увидеть все имеющиеся там файлы / папки. чтобы проверить текущий рабочий каталог, перейдите в консоль IDE spyder и просто наберите
pwd
он напечатает тот же путь, который вы выбрали ранее.
Изменение текущей директории процесса скрипта тривиально. Я думаю, что на самом деле вопрос заключается в том, как изменить текущий каталог командного окна, из которого вызывается скрипт Python, что очень сложно. Сценарий Bat в Windows или сценарий Bash в оболочке Bash могут сделать это с помощью обычной команды cd, поскольку сама оболочка является интерпретатором. И в Windows, и в Linux Python - это программа, и никакая программа не может напрямую изменить среду своего родителя. Однако сочетание простого сценария оболочки с сценарием Python, выполняющего большинство сложных задач, может достичь желаемого результата. Например, чтобы создать расширенную команду cd с историей обхода для возврата назад / вперед / выбора, я написал относительно сложный скрипт Python, вызываемый простым скриптом bat. Список прохождения хранится в файле, с целевым каталогом в первой строке. Когда скрипт python возвращается, скрипт bat читает первую строку файла и делает его аргументом для cd. Полный скрипт (без комментариев для краткости):
if _%1== _. goto cdDone
if _%1== _? goto help
if/i _%1 NEQ _-H goto doCd
:help
echo d.bat and dSup.py 2016.03.05.Extended chdir.
echo -C = clear traversal list.
echo -B or nothing = backward (to previous dir).
echo -F or-= forward (to next dir).
echo -R = remove current from list andreturn to previous.
echo -S = select from list.
echo -H,-h,?= help.
echo .= make window title current directory.
echo Anythingelse= target directory.
goto done
:doCd
%~dp0dSup.py %1for/F %%d in(%~dp0dSupList )do(
cd %%d
if errorlevel 1(%~dp0dSup.py -R )
goto cdDone
):cdDone
title %CD%:done
Сценарий Python, dSup.py:
import sys, os, msvcrt
def indexNoCase ( slist, s ):for idx in range( len( slist )):if slist[idx].upper()== s.upper():return idx
raiseValueError# .........main process ...................if len( sys.argv )<2:
cmd =1# No argument defaults to -B, the most common operationelif sys.argv[1][0]=='-':if len(sys.argv[1])==1:
cmd =2# '-' alone defaults to -F, second most common operation.else:
cmd ='CBFRS'.find( sys.argv[1][1:2].upper())else:
cmd =-1
dir = os.path.abspath( sys.argv[1])+'\n'# cmd is -1 = path, 0 = C, 1 = B, 2 = F, 3 = R, 4 = S
fo = open( os.path.dirname( sys.argv[0])+'\\dSupList', mode ='a+t')
fo.seek(0)
dlist = fo.readlines(-1)if len( dlist )==0:
dlist.append( os.getcwd()+'\n')# Prime new directory list with current.if cmd ==1:# B: move backward, i.e. to previous
target = dlist.pop(0)
dlist.append( target )elif cmd ==2:# F: move forward, i.e. to next
target = dlist.pop( len( dlist )-1)
dlist.insert(0, target )elif cmd ==3:# R: remove current from list. This forces cd to previous, a# desireable side-effect
dlist.pop(0)elif cmd ==4:# S: select from list# The current directory (dlist[0]) is included essentially as ESC.for idx in range( len( dlist )):print('('+ str( idx )+')', dlist[ idx ][:-1])whileTrue:
inp = msvcrt.getche()if inp.isdigit():
inp = int( inp )if inp < len( dlist ):print('')# Print the newline we didn't get from getche.breakprint(' is out of range')# Select 0 means the current directory and the list is not changed. Otherwise# the selected directory is moved to the top of the list. This can be done by# either rotating the whole list until the selection is at the head or pop it# and insert it to 0. It isn't obvious which would be better for the user but# since pop-insert is simpler, it is used.if inp >0:
dlist.insert(0, dlist.pop( inp ))elif cmd ==-1:# -1: dir is the requested new directory.# If it is already in the list then remove it before inserting it at the head.# This takes care of both the common case of it having been recently visited# and the less common case of user mistakenly requesting current, in which# case it is already at the head. Deleting and putting it back is a trivial# inefficiency.try:
dlist.pop( indexNoCase( dlist, dir ))exceptValueError:pass
dlist = dlist[:9]# Control list length by removing older dirs (should be# no more than one).
dlist.insert(0, dir )
fo.truncate(0)if cmd !=0:# C: clear the list
fo.writelines( dlist )
fo.close()
exit(0)
Хотя это хороший ответ, OP выбрал ответ, который говорит, что речь не идет об изменении CWD родительского процесса. Это проясняет любую возможную путаницу в том, что означает вопрос.
Жестянщик
To Tin Man-- этот ответ был выбран до того, как я опубликовал свое предложение. Я думаю, что ответы на самые разные вопросы могли сбить с толку. cd в данном процессе (например, скрипт на python) настолько прост, что я не знаю, почему кто-то спросил бы его.
Дэвид МакКракен,
1
На самом деле этот ответ был выбран несколько лет назад. Если бы это не было уместно, с тех пор его вызывали бы много раз.
Жестянщик
Я думаю, что путаница остается. Совсем недавно вопрос «имитация команды Linux« cd »в python и сохранение изменения каталога после выхода из программы [duplicate]» был отклонен как ответ здесь, но на самом деле этот вопрос не решен в выбранном ответе. Мое предложение для Windows, но проблемы те же в Linux.
os.chdir(os.path.join(os.path.abspath(os.path.curdir),u'subfolder'))
- или?os.getcwd()
Ответы:
Вы можете изменить рабочий каталог с помощью:
При использовании этого метода необходимо следовать двум рекомендациям:
Изменение текущего рабочего каталога в подпроцессе не приводит к изменению текущего рабочего каталога в родительском процессе. Это верно и для интерпретатора Python. Вы не можете использовать
os.chdir()
для изменения CWD вызывающего процесса.источник
os.chdir()
вне контекстного менеджера, если только вы не думаете, что знаете, что делаете. ( Вы, вероятно, не. )os.chdir("C:/path/to/location")
Вот пример контекстного менеджера для изменения рабочего каталога. Это проще, чем версия ActiveState, о которой говорится в другом месте, но это делает работу.
Диспетчер контекста:
cd
Или попробуйте более краткий эквивалент (ниже) , используя ContextManager .
пример
источник
return self
в конце__enter__
. Таким образом, вы можете сделатьwith cd('foo') as cm:
и получить доступ к предыдущему каталогу, какcm.savedPath
Я бы использовал
os.chdir
так:Кстати, если вам нужно выяснить ваш текущий путь, используйте
os.getcwd()
.Больше здесь
источник
cd()
легко написать с помощью генератора и декоратора.Затем каталог восстанавливается даже после возникновения исключения:
источник
try/finally
).yield
и нетreturn
? Это должен быть генератор?Если вы используете относительно новую версию Python, вы также можете использовать менеджер контекста, такой как этот :
ОБНОВИТЬ
Если вы предпочитаете кататься самостоятельно:
источник
contextlib.contextmanager
декоратор хорош. Смотрите ответ cdunn2001 на основе декоратора , который в идеале был бы принятым ответом сейчас.Как уже указывалось другими, все решения, приведенные выше, меняют только рабочий каталог текущего процесса. Это теряется при выходе из оболочки Unix. Если вы в отчаянии, вы можете изменить каталог родительской оболочки в Unix с помощью этого ужасного хака:
источник
os.chdir()
это правильный путь.источник
os.chdir()
это Pythonic версияcd
.источник
Вы можете использовать оба с os.chdir (abs_path) или os.chdir (rel_path), нет необходимости вызывать os.getcwd (), чтобы использовать относительный путь.
источник
Далее в направлении, указанном Брайаном и основанном на sh (1.0.8+)
источник
Если вы хотите выполнить что-то вроде «cd ..», просто наберите:
os.chdir ( "..")
это то же самое, что и в Windows cmd: cd. Конечно, необходим импорт os (например, введите его в качестве первой строки вашего кода)
источник
Если вы используете spyder и love GUI, вы можете просто нажать на кнопку папки в верхнем правом углу экрана и перемещаться по папкам / каталогам, которые вы хотите использовать в качестве текущего каталога. После этого вы можете перейти на вкладку «Обозреватель файлов» окна в IDE spyder и увидеть все имеющиеся там файлы / папки. чтобы проверить текущий рабочий каталог, перейдите в консоль IDE spyder и просто наберите
он напечатает тот же путь, который вы выбрали ранее.
источник
Изменение текущей директории процесса скрипта тривиально. Я думаю, что на самом деле вопрос заключается в том, как изменить текущий каталог командного окна, из которого вызывается скрипт Python, что очень сложно. Сценарий Bat в Windows или сценарий Bash в оболочке Bash могут сделать это с помощью обычной команды cd, поскольку сама оболочка является интерпретатором. И в Windows, и в Linux Python - это программа, и никакая программа не может напрямую изменить среду своего родителя. Однако сочетание простого сценария оболочки с сценарием Python, выполняющего большинство сложных задач, может достичь желаемого результата. Например, чтобы создать расширенную команду cd с историей обхода для возврата назад / вперед / выбора, я написал относительно сложный скрипт Python, вызываемый простым скриптом bat. Список прохождения хранится в файле, с целевым каталогом в первой строке. Когда скрипт python возвращается, скрипт bat читает первую строку файла и делает его аргументом для cd. Полный скрипт (без комментариев для краткости):
Сценарий Python, dSup.py:
источник