Эквивалент команды оболочки cd для изменения рабочего каталога?

cd - это команда оболочки для изменения рабочего каталога.

Как изменить текущий рабочий каталог в Python?

Так в интерпретаторе os.chdir(os.path.join(os.path.abspath(os.path.curdir),u'subf‌​older')) - или?

Mr_and_Mrs_D 26.12.2014 18:31

Интересно в этом контексте: Найти текущий каталог и каталог с файлом: os.getcwd()

Martin Thoma 20.12.2017 13:34
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
760
2
1 229 996
14
Перейти к ответу Данный вопрос помечен как решенный

Ответы 14

os.chdir() - это питоническая версия cd.

os.chdir() - правильный путь.

Ответ принят как подходящий

Вы можете изменить рабочий каталог с помощью:

import os

os.chdir(path)

При использовании этого метода следует придерживаться двух рекомендаций:

  1. Поймать исключение (WindowsError, OSError) на недопустимом пути. Если возникло исключение, не выполняйте никаких рекурсивных операций, особенно деструктивных. Они будут действовать по старому пути, а не по новому.
  2. Когда закончите, вернитесь в свой старый каталог. Это можно сделать безопасным для исключений способом, заключив вызов chdir в диспетчер контекста, как это сделал Брайан М. Хант в его ответ.

Изменение текущего рабочего каталога в подпроцессе не изменяет текущий рабочий каталог в родительском процессе. Это верно и для интерпретатора Python. Вы не можете использовать os.chdir() для изменения CWD вызывающего процесса.

Облегченный ответ на основе декоратораcdunn2001 - идеальный подход для современного Python. Приведенный выше ответ демонстрирует, почему. Никогда не вызывайте os.chdir() вне контекстного менеджера,, если вы не думаете, что знаете, что делаете. (Вероятно, вы этого не сделаете.)

Cecil Curry 22.05.2016 08:19

Думаю, это самый простой способ в интерактивной оболочке. Обратите внимание, что в Windows вы должны использовать косую черту, например os.chdir("C:/path/to/location").

Josiah 25.07.2016 14:45

Единственное, о чем следует знать, - это то, что если вы сделаете свою программу python исполняемым файлом и запустите ее в cron, она запустится в вашем домашнем каталоге. Поэтому лучше использовать полностью определенный путь. Это определенно работает, но я все еще использую полностью определенные пути в любом скрипте, который могу вызвать из Python, потому что нет гарантии, что это будет применяться вне самой программы Python.

SDsolar 02.08.2017 06:43

Я бы использовал os.chdir вот так:

os.chdir("/path/to/change/to")

Кстати, если вам нужно выяснить ваш текущий путь, используйте os.getcwd().

Подробнее здесь

Если вы используете относительно новую версию Python, вы также можете использовать диспетчер контекста, например Вот этот:

from __future__ import with_statement
from grizzled.os import working_directory

with working_directory(path_to_directory):
    # code in here occurs within the directory

# code here is in the original directory

ОБНОВИТЬ

Если вы предпочитаете кататься самостоятельно:

import os
from contextlib import contextmanager

@contextmanager
def working_directory(directory):
    owd = os.getcwd()
    try:
        os.chdir(directory)
        yield directory
    finally:
        os.chdir(owd)

Хорошая общая идея. Здесь Рецепт Activestate без других зависимостей.

cfi 26.09.2012 17:43
Зависимости плохие. Встроенный в Python декоратор contextlib.contextmanager хорош. См. ответ на основе декоратораcdunn2001, который в идеале был бы сейчас принятым ответом.
Cecil Curry 22.05.2016 08:10

Вот пример диспетчера контекста для изменения рабочего каталога. Это проще, чем упоминаемый в другом месте Версия ActiveState, но он выполняет свою работу.

Контекстный менеджер: cd

import os

class 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)

Или попробуйте более лаконичный эквивалент (ниже), используя ContextManager.

Пример

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.

Sam F 27.03.2018 10:35

Обратите внимание, что есть случаи, когда возврат в старый каталог (тот, который хранится в «savedPath») невозможен. Например, если более привилегированный процесс выполняет менее привилегированный процесс, второй процесс наследует рабочий каталог первого процесса, даже в тех случаях, когда второй процесс не может войти в этот рабочий каталог со своими собственными возможностями.

Kai Petzke 11.02.2019 12:43

Я получаю следующее предупреждающее сообщение: Attribute 'savedPath' defined outside __init__ [attribute-defined-outside-init]

alper 01.02.2021 19:37

Как уже указывалось другими, все вышеперечисленные решения изменяют только рабочий каталог текущего процесса. Это теряется, когда вы возвращаетесь в оболочку Unix. Если вы в отчаянии, вы может измените родительский каталог оболочки в Unix с помощью этого ужасного взлома:

def quote_against_shell_expansion(s):
    import pipes
    return 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, termios
    for 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")
Безумный, хрупкий хакер получает обязательные голоса. Никто никогда не должен этого делать, особенно с предостережением "и если пользователь печатает во время его выполнения ...". Тем не менее, во мне щекотал мятежник, видя, что изменение родительского CWD является вроде как, но не совсем осуществимо. Голосов за! Голосов за всех!
Cecil Curry 22.05.2016 08:06

Далее в направлении, указанном Брайаном и основанном на ш (1.0.8+)

from sh import cd, ls

cd('/tmp')
print ls()

cd() легко написать с помощью генератора и декоратора.

from contextlib import contextmanager
import os

@contextmanager
def cd(newdir):
    prevdir = os.getcwd()
    os.chdir(os.path.expanduser(newdir))
    try:
        yield
    finally:
        os.chdir(prevdir)

Затем каталог возвращается в исходное состояние даже после создания исключения:

os.chdir('/home')

with cd('/tmp'):
    # ...
    raise Exception("There's no place like /home.")
# Directory is now back to '/home'.

Также обратите внимание на эта потенциальная ошибка (чтобы забыть о try/finally).

cdunn2001 27.12.2014 00:59
Блеск! Если бы вводный комментарий из принятый ответ был вставлен в ответ это, это было бы неизмеримо идеально. Тем не менее, этот краткий ответ, безопасная для Python реализация гарантирует все положительные голоса, которые я должен дать.
Cecil Curry 22.05.2016 08:13

Почему yield, а не return? Это должен быть генератор?

EKons 05.08.2016 12:19

Прокомментируйте, пожалуйста, соотношение доходности и доходности!

NicoBerrogorry 18.07.2017 08:27

@NicoBerrogorry, это генератор. См. Документы на contextlib.contextmanager. Это очень полезный шаблон в Python, который стоит изучить.

cdunn2001 11.09.2017 21:52

Я хотел бы наконец спросить об использовании. Мы знаем, что, наконец, всегда происходит после попытки, исключения или нет. Хотя это нормально, когда есть исключение, это также означает, что в любом случае вы вернетесь в предыдущий каталог, а это не то, что планировалось. Разве os.chdir (prevdir) не должен находиться под оператором else? Кроме того, мне интересно, почему python subprocess.call ("cd / path") на самом деле не работает ...

Ando Jurai 10.11.2017 13:14

Почему в конце блока raise Exception стоит with?

alper 08.07.2020 23:18

@AndoJurai Я действительно думаю, что всегда следует возвращаться в предыдущий каталог. Таким образом, структура вашего кода соответствует структуре каталогов, и вам не нужно устанавливать cd('../'), о котором легко забыть.

Libavius 14.01.2021 17:52

Изменение текущего каталога процесса сценария тривиально. Я думаю, что на самом деле вопрос заключается в том, как изменить текущий каталог командного окна, из которого вызывается скрипт python, что очень сложно. Сценарий Bat в Windows или сценарий Bash в оболочке Bash может сделать это с помощью обычной команды cd, поскольку интерпретатором является сама оболочка. И в Windows, и в Linux Python - это программа, и никакая программа не может напрямую изменять родительскую среду. Однако сочетание простого сценария оболочки со сценарием Python, выполняющим большую часть сложных задач, может достичь желаемого результата. Например, чтобы создать расширенную команду cd с историей обхода для обратного / прямого / выбора повторного посещения, я написал относительно сложный сценарий Python, вызываемый простым сценарием летучей мыши. Список обхода сохраняется в файле с целевым каталогом в первой строке. Когда сценарий 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 and return to previous.
echo -S = select from list.
echo -H, -h, ? = help.
echo . = make window title current directory.
echo Anything else = target directory.
goto done

:doCd
%~dp0dSup.py %1
for /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
    raise ValueError

# .........main process ...................
if len( sys.argv ) < 2 :
    cmd = 1 # No argument defaults to -B, the most common operation
elif 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])
    while True :
        inp = msvcrt.getche()
        if inp.isdigit() :
            inp = int( inp )
            if inp < len( dlist ) :
                print( '' ) # Print the newline we didn't get from getche.
                break
        print( ' 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 ))
    except ValueError :
        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 родительского процесса. Это устраняет любую возможную путаницу в том, что означает вопрос.

the Tin Man 11.04.2016 21:54

Toin Man - этот ответ был выбран до того, как я опубликовал свое предложение. Я думаю, что широкий диапазон ответов мог сбить с толку. cd в данном процессе (например, скрипт Python) настолько прост, что я не знаю, почему кто-то может спросить об этом.

David McCracken 13.04.2016 07:11

Собственно этот ответ был выбран годы назад. Если бы это было неуместно, то с тех пор его вызывали бы много раз.

the Tin Man 13.04.2016 19:13

Я думаю, что путаница сохраняется. Совсем недавно вопрос «имитировать команду linux« cd »в python и сохранить изменение каталога после выхода из программы [дубликат]» был отклонен, поскольку здесь был дан ответ, но на самом деле этот вопрос не рассматривается в выбранном ответе. Мое предложение относится к Windows, но в Linux проблемы те же.

David McCracken 15.04.2016 22:46

Если вы хотите выполнить что-то вроде опции «cd ..», просто введите:

os.chdir ("..")

это то же самое, что и в Windows cmd: cd .. Конечно, импорт ОС необходим (например, введите его как 1-ю строку вашего кода)

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 () для использования относительного пути.

Работает хорошо. Можно использовать os.getcwd () для проверки текущего каталога как до, так и после изменения каталога.

vinsinraw 04.01.2019 00:38

Если вы используете Spyder и любите графический интерфейс, вы можете просто нажать кнопку папки в правом верхнем углу экрана и перемещаться по папкам / каталогам, которые вы хотите использовать в качестве текущего каталога. После этого вы можете перейти на вкладку проводника в окне в spyder IDE и увидеть все файлы / папки, которые там присутствуют. чтобы проверить текущий рабочий каталог перейдите в консоль IDE Spyder и просто введите

pwd

он напечатает тот же путь, который вы выбрали ранее.

Объекты Path в библиотеке дорожка предлагают для этой цели как диспетчер контекста, так и метод chdir:

from path import Path

with Path("somewhere"):
    ...

Path("somewhere").chdir()

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