파이썬에서 작업 디렉토리를 어떻게 변경합니까?


답변:


766

다음을 사용하여 작업 디렉토리를 변경할 수 있습니다.

import os

os.chdir(path)

이 방법을 사용할 때 따라야 할 두 가지 모범 사례가 있습니다.

  1. 잘못된 경로에서 예외 (WindowsError, OSError)를 포착하십시오. 예외가 발생하면 재귀 작업, 특히 파괴적인 작업을 수행하지 마십시오. 그들은 새로운 경로가 아닌 오래된 경로에서 작동합니다.
  2. 완료되면 이전 디렉토리로 돌아갑니다. 이것은 Brian M. Hunt가 그의 답변 에서했던 것처럼 컨텍스트 관리자에 chdir 호출을 래핑하여 예외 안전 방식으로 수행 할 수 있습니다 .

서브 프로세스에서 현재 작업 디렉토리를 변경해도 상위 프로세스의 현재 작업 디렉토리는 변경되지 않습니다. 이것은 파이썬 인터프리터에서도 마찬가지입니다. os.chdir()호출 프로세스의 CWD를 변경하는 데 사용할 수 없습니다 .


3
cdunn2001 의 경량 데코레이터 기반 답변 은 현대 파이썬에 이상적인 접근 방식입니다. 위의 대답은 이유를 보여줍니다. 자신이하고있는 일을 모른다고 생각하지 않는 한 컨텍스트 관리자 외부에 전화하지 마십시오os.chdir() . ( 아마도 아닐 것입니다. )
Cecil Curry

6
이것은 대화 형 쉘에서 가장 쉬운 방법이라고 생각합니다. Windows에서는 다음과 같이 슬래시를 사용해야합니다.os.chdir("C:/path/to/location")
Josiah

알아야 할 한 가지는 파이썬 프로그램을 실행 파일로 만들고 cron에서 실행하면 홈 디렉토리에서 시작된다는 것입니다. 따라서 정규화 된 경로를 사용하는 것이 가장 좋습니다. 이것은 확실히 작동하지만 파이썬에서 호출 할 수있는 모든 스크립트에서 여전히 완전한 경로를 사용합니다. 파이썬 프로그램 외부에서 적용될 것이라는 보장은 없기 때문입니다.
SDsolar 2012 년

310

다음은 작업 디렉토리를 변경하는 컨텍스트 관리자의 예입니다. 다른 곳에서 참조 되는 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.

FROM을 변경 한 디렉토리를 알아야 할 return self경우 끝에 추가하면 됩니다 __enter__. 그렇게하면 다음 with cd('foo') as cm:과 같이 이전 디렉토리에 액세스하고 액세스 할 수 있습니다cm.savedPath
Sam F

이전 디렉토리 ( "savedPath"에 저장된 디렉토리)로 리턴 할 수없는 경우가 있습니다. 예를 들어, 권한이 더 높은 프로세스가 권한이 낮은 프로세스를 실행하는 경우 두 번째 프로세스는 첫 번째 프로세스 작업 디렉토리를 상속합니다.이 경우에도 두 번째 프로세스가 자체 기능으로 작업 디렉토리에 들어갈 수 없습니다.
카이 Petzke

141

나는 os.chdir이것을 다음과 같이 사용할 것이다 :

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

그런데 현재 경로를 알아 내야하는 경우을 사용하십시오 os.getcwd().

여기


117

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'.

3
또한 이 잠재적 실수는 (을 잊어 버리기 위해 try/finally) 참고 하십시오 .
cdunn2001

5
광휘! 수락 된 답변 의 소개 주석 이이 답변에 주입 된 경우 , 이는 매우 이상적입니다. 그럼에도 불구 하고이 대답의 간결하고 파이썬으로 안전한 구현은 내가 제공 해야하는 모든 공감대를 보증합니다.
Cecil Curry

3
yield그렇지 return않습니까? 이것은 발전기로되어 있습니까?
EKons

수익률과 수익률의 관련성에 대해 의견을 주시기 바랍니다!
NicoBerrogorry

1
@NicoBerrogorry, 그것은 발전기입니다. contextlib.contextmanager의 문서를 참조하십시오 . 이것은 파이썬에서 학습 할 가치가있는 매우 유용한 패턴입니다.
cdunn2001

25

파이썬의 비교적 새로운 버전을 사용하는 경우, 당신은 또한 같은 맥락 관리자를 사용할 수 있습니다 이 하나 :

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)

1
좋은 생각입니다. 에 여기 ActiveState의 레시피 다른 종속성 않고있다.
cfi

4
의존성이 나쁘다. 파이썬의 내장 contextlib.contextmanager데코레이터가 좋습니다. cdunn2001데코레이터 기반 답변을 참조하십시오 .이 답변은 현재 가장 적합한 답변입니다.
세실 커리

14

다른 사람들이 이미 지적했듯이 위의 모든 솔루션은 현재 프로세스의 작업 디렉토리 만 변경합니다. 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")

4
미친, 연약한 해킹은 필수 공감대를 가져옵니다. 특히 "사용자가 실행하는 동안 입력하면 ..."경고를 사용하여이 작업을 수행해서는 안됩니다. 그럼에도 불구하고, 그것은 부모 CWD를 바꾸는 것이 일종의 것이지만 실제로 실현 가능하지 않다는 것을 알기 위해 반란군의 목을 품고 있습니다. 공감! 모두를위한 공감!
Cecil Curry


11

os.chdir()의 Pythonic 버전입니다 cd.


8
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


3

"cd .."옵션과 같은 작업을 수행하려면 다음을 입력하십시오.

os.chdir ( "..")

Windows cmd : cd와 동일합니다. 물론 import os 는 필요합니다 (예 : 코드의 첫 번째 줄로 입력).


0

spyder and love GUI를 사용하는 경우 화면 오른쪽 상단의 폴더 버튼을 클릭하고 현재 디렉토리로 원하는 폴더 / 디렉토리를 탐색하면됩니다. 그런 다음 spyder IDE에서 창의 파일 탐색기 탭으로 이동하면 거기에있는 모든 파일 / 폴더를 볼 수 있습니다. 현재 작업 디렉토리를 확인하려면 spyder IDE의 콘솔로 이동하여 간단히 입력하십시오.

pwd

이전에 선택한 것과 동일한 경로를 인쇄합니다.


-1

스크립트 프로세스의 현재 디렉토리를 변경하는 것은 쉽지 않습니다. 나는 실제로 파이썬 스크립트가 호출되는 명령 창의 현재 디렉토리를 변경하는 방법에 대한 질문이라고 생각합니다. 매우 어렵습니다. 쉘 자체가 인터프리터이기 때문에 Windows의 박쥐 스크립트 또는 Bash 쉘의 Bash 스크립트는 일반 cd 명령으로이를 수행 할 수 있습니다. Windows와 Linux에서 Python은 프로그램이며 부모의 환경을 직접 변경할 수있는 프로그램은 없습니다. 그러나 간단한 쉘 스크립트와 대부분의 어려운 작업을 수행하는 Python 스크립트를 결합하면 원하는 결과를 얻을 수 있습니다. 예를 들어, 뒤로 / 앞으로 / 선택 재 방문을위한 순회 히스토리가있는 확장 cd 명령을 작성하기 위해 간단한 bat 스크립트로 호출되는 비교적 복잡한 Python 스크립트를 작성했습니다. 순회 목록은 파일에 저장됩니다. 첫 번째 행에 대상 디렉토리가 있습니다. python 스크립트가 반환되면 bat 스크립트는 파일의 첫 번째 줄을 읽고 cd의 인수로 만듭니다. 완전한 bat 스크립트 (간결한 설명 제외)는 다음과 같습니다.

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

파이썬 스크립트 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를 변경하는 것이 아니라는 답변을 선택했습니다. 그러면 질문의 의미에 대한 혼란이 사라집니다.
Tin Man

Tin Man에게-그 대답은 제가 제안을 게시하기 전에 선택되었습니다. 나는 광범위한 답변이 혼란 스러울 수 있다고 생각합니다. 주어진 프로세스 내에서 CD (예 : 파이썬 스크립트)는 너무 간단하여 누군가가 왜 그것을 물어볼 지 모르겠습니다.
David McCracken

1
실제로 그 대답은 몇 년 전에 선택 되었습니다. 적절하지 않다면 그 이후로 여러 번 호출되었을 것입니다.
Tin Man

혼란이 남아 있다고 생각합니다. 더 최근에는 "python에서 linux의"cd "명령을 시뮬레이션하고 프로그램이 종료 된 후에도 디렉토리 변경을 유지합니다 [duplicate]"라는 질문이 여기에서 답변 된 것으로 사라지지만 실제로이 질문은 선택된 답변으로 해결되지 않습니다. 내 제안은 Windows에 대한 것이지만 Linux에서는 문제가 동일합니다.
David McCracken
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.