파일을 작성할 디렉토리가 존재하는지 여부를 확인하고 그렇지 않은 경우 Python을 사용하여 디렉토리를 작성하는 가장 우아한 방법은 무엇입니까? 내가 시도한 것은 다음과 같습니다.
import os
file_path = "/my/directory/filename.txt"
directory = os.path.dirname(file_path)
try:
os.stat(directory)
except:
os.mkdir(directory)
f = file(filename)
어떻게 든, 나는 놓쳤다 os.path.exists
(kanja, Blair와 Douglas에게 감사한다). 이것이 내가 지금 가진 것입니다.
def ensure_dir(file_path):
directory = os.path.dirname(file_path)
if not os.path.exists(directory):
os.makedirs(directory)
“open”에 대한 플래그가 있습니까? 자동으로 발생합니까?
답변
Python ≥ 3.5에서는 다음을 사용하십시오 pathlib.Path.mkdir
.
from pathlib import Path
Path("/my/directory").mkdir(parents=True, exist_ok=True)
이전 버전의 Python의 경우 작은 결함이있는 좋은 품질의 두 가지 답변을 보았습니다.
시도 하고 창조를 os.path.exists
고려 하십시오 os.makedirs
.
import os
if not os.path.exists(directory):
os.makedirs(directory)
의견과 다른 곳에서 언급했듯이 경쟁 조건이 있습니다. 디렉토리가 os.path.exists
와 os.makedirs
호출 사이에 생성 os.makedirs
되면는로 실패합니다 OSError
. 불행히도, OSError
불완전한 권한, 전체 디스크 등과 같은 다른 요인으로 인해 디렉토리를 만들지 못하는 것을 무시할 수 있기 때문에 담요 잡기 및 계속은 절대 쉽지 않습니다.
하나의 옵션은 OSError
포함 된 오류 코드 를 포착 하고 검사하는 것입니다 (Python의 OSError에서 정보를 가져 오는 플랫폼 간 방법이 있습니까)를 참조하십시오 .
import os, errno
try:
os.makedirs(directory)
except OSError as e:
if e.errno != errno.EEXIST:
raise
또는 두 번째가있을 수 os.path.exists
있지만 다른 첫 번째 검사 후에 디렉토리를 만든 다음 두 번째 검사 전에 디렉토리를 제거했다고 가정합니다. 여전히 속일 수 있습니다.
응용 프로그램에 따라 동시 작업의 위험은 파일 권한과 같은 다른 요인으로 인한 위험보다 많거나 적을 수 있습니다. 개발자는 구현을 선택하기 전에 개발중인 특정 응용 프로그램과 예상 환경에 대해 더 많이 알아야합니다.
최신 버전의 Python FileExistsError
은 (3.3 이상에서) 노출 함으로써이 코드를 상당히 개선합니다 …
try:
os.makedirs("path/to/directory")
except FileExistsError:
# directory already exists
pass
… 그리고 키워드 인수가 os.makedirs
호출exist_ok
되도록 허용 합니다 (3.2 이상).
os.makedirs("path/to/directory", exist_ok=True) # succeeds even if directory exists.
답변
파이썬 3.5 이상 :
import pathlib
pathlib.Path('/my/directory').mkdir(parents=True, exist_ok=True)
pathlib.Path.mkdir
위에서 사용한대로 디렉토리를 재귀 적으로 작성하고 디렉토리가 이미 존재하는 경우 예외를 발생시키지 않습니다. 부모를 만들거나 필요로하지 않으려면 parents
인수를 건너 뜁니다 .
파이썬 3.2 이상 :
사용 pathlib
:
가능하면 pathlib
이라는 현재 백 포트를 설치하십시오 pathlib2
. 이름이없는 유지 관리되지 않은 이전 백 포트를 설치하지 마십시오 pathlib
. 다음으로 위의 Python 3.5+ 섹션을 참조하여 동일하게 사용하십시오.
Python 3.4를 사용하는 경우와 함께 제공되지만 pathlib
유용한 exist_ok
옵션 이 누락되었습니다 . 백 포트는 mkdir
이 누락 된 옵션을 포함 하는 새롭고 우수한 구현을 제공하기위한 것 입니다.
사용 os
:
import os
os.makedirs(path, exist_ok=True)
os.makedirs
위에서 사용한대로 디렉토리를 재귀 적으로 작성하고 디렉토리가 이미 존재하는 경우 예외를 발생시키지 않습니다. exist_ok
Python 3.2 이상을 사용하는 경우에만 선택적 인수가 있으며 기본값은 False
입니다. 이 인수는 Python 2.x에서 2.7까지 존재하지 않습니다. 따라서 Python 2.7에서와 같이 수동 예외 처리가 필요하지 않습니다.
파이썬 2.7+ :
사용 pathlib
:
가능하면 pathlib
이라는 현재 백 포트를 설치하십시오 pathlib2
. 이름이없는 유지 관리되지 않은 이전 백 포트를 설치하지 마십시오 pathlib
. 다음으로 위의 Python 3.5+ 섹션을 참조하여 동일하게 사용하십시오.
사용 os
:
import os
try:
os.makedirs(path)
except OSError:
if not os.path.isdir(path):
raise
나이브 용액을 먼저 사용할 수도 있지만 os.path.isdir
다음 os.makedirs
반전 두 동작들의 순서 상기 용액. 이렇게하면 디렉토리를 만들려는 중복 된 시도와 관련된 일반적인 경쟁 조건이 방지되고 디렉토리에서 파일이 명확 해집니다.
예를 들어 , 파일과 디렉토리 모두에 대해 예외가 발생하여 사용하는 errno
것은 유용성이 제한적 입니다. 디렉토리가 존재하는지 확인하는 것이 더 안정적입니다.OSError: [Errno 17] File exists
errno.EEXIST
대안 :
mkpath
중첩 된 디렉토리를 작성하고 디렉토리가 이미 존재하면 아무 것도 수행하지 않습니다. 이것은 Python 2와 3에서 모두 작동합니다.
import distutils.dir_util
distutils.dir_util.mkpath(path)
버그 10948 당 ,이 대안의 심각한 제한은 주어진 경로에 대해 파이썬 프로세스 당 한 번만 작동한다는 것입니다. 즉, 디렉토리를 생성하기 위해 디렉토리를 사용하는 경우 Python 내부 또는 외부에서 디렉토리를 삭제 한 다음 mkpath
다시 사용 하여 동일한 디렉토리를 다시 mkpath
생성하고 이전에 디렉토리를 생성 한 잘못된 캐시 된 정보를 자동으로 사용합니다. 실제로 디렉토리를 다시 만드십시오. 대조적으로, os.makedirs
그러한 캐시에 의존하지 않습니다. 일부 응용 프로그램에서는이 제한이 적용됩니다.
디렉토리 모드 와 관련하여 관심이있는 경우 문서를 참조하십시오.
답변
errno 모듈의 try except 및 올바른 오류 코드를 사용하면 경쟁 조건이 제거되고 크로스 플랫폼이 있습니다.
import os
import errno
def make_sure_path_exists(path):
try:
os.makedirs(path)
except OSError as exception:
if exception.errno != errno.EEXIST:
raise
다시 말해 디렉토리를 만들려고하지만 이미 존재하는 경우 오류를 무시합니다. 반면에 다른 오류는보고됩니다. 예를 들어, 사전에 dir ‘a’를 작성하고 모든 권한을 제거하면 (권한 거부, 오류 13) OSError
과 함께 발생 errno.EACCES
합니다.
답변
개인적으로 os.path.isdir()
대신 테스트에 사용 하는 것이 좋습니다 os.path.exists()
.
>>> os.path.exists('/tmp/dirname')
True
>>> os.path.exists('/tmp/dirname/filename.etc')
True
>>> os.path.isdir('/tmp/dirname/filename.etc')
False
>>> os.path.isdir('/tmp/fakedirname')
False
당신이 가지고 있다면:
>>> dir = raw_input(":: ")
그리고 어리석은 사용자 입력 :
:: /tmp/dirname/filename.etc
…로 테스트하면 filename.etc
인수를 전달할 때 이름이 지정된 디렉토리로 끝납니다 .os.makedirs()
os.path.exists()
답변
점검 os.makedirs
: (전체 경로가 존재하는지 확인하십시오.)
디렉토리가 존재할 수있는 사실을 처리하려면 catch하십시오 OSError
. ( exist_ok
is False
(기본값) 인 OSError
경우 대상 디렉토리가 이미 존재하면 ) 가 발생합니다.
import os
try:
os.makedirs('./path/to/somewhere')
except OSError:
pass
답변
파이썬 3.5부터 pathlib.Path.mkdir
이 exist_ok
플래그를 :
from pathlib import Path
path = Path('/my/directory/filename.txt')
path.parent.mkdir(parents=True, exist_ok=True)
# path.parent ~ os.path.dirname(path)
이는 재귀 적으로 디렉토리를 작성하며 디렉토리가 이미 존재하는 경우 예외를 발생시키지 않습니다.
( 파이썬 3.2에서 시작 os.makedirs
하는 exist_ok
플래그 가있는 것처럼 os.makedirs(path, exist_ok=True)
)
답변
이 상황의 특성에 대한 통찰력
특정 경로에 특정 파일을 제공하고 파일 경로에서 디렉토리를 가져옵니다. 그런 다음 디렉토리가 있는지 확인한 후 읽을 파일을 열려고 시도하십시오. 이 코드에 주석을 달려면
filename = "/my/directory/filename.txt" dir = os.path.dirname(filename)
내장 함수 덮어 쓰기를 피하고 싶습니다 dir
. 또한, filepath
아마도 아마도 아마도 fullfilepath
더 나은 의미 론적 이름 filename
이므로 아마도 더 잘 쓰여질 것입니다 :
import os
filepath = '/my/directory/filename.txt'
directory = os.path.dirname(filepath)
최종 목표는 쓰기를 들어, 처음에이 파일을 열 수 상태,하지만 당신은 본질적으로의 파일을 열어이 같은 (코드 기준)이 목표에 접근하고 읽기 :
if not os.path.exists(directory): os.makedirs(directory) f = file(filename)
독서를위한 오프닝 가정
거기에 있고 읽을 수있는 파일의 디렉토리를 만드는 이유는 무엇입니까?
파일을 열어보십시오.
with open(filepath) as my_file:
do_stuff(my_file)
디렉토리 또는 파일이 없으면 IOError
관련 오류 번호 errno.ENOENT
가 나타납니다. 플랫폼에 관계없이 올바른 오류 번호를 가리 킵니다. 원하는 경우 다음과 같이 잡을 수 있습니다.
import errno
try:
with open(filepath) as my_file:
do_stuff(my_file)
except IOError as error:
if error.errno == errno.ENOENT:
print 'ignoring error because directory or file is not there'
else:
raise
우리가 글쓰기를 시작한다고 가정
이다 아마 당신이 원하는 것입니다.
이 경우 경쟁 조건이 없을 수 있습니다. 따라서 그대로 작업을 수행하지만 쓰기를 위해서는 w
모드 로 열어야 합니다 (또는 a
추가해야 함). 컨텍스트 관리자를 사용하여 파일을 여는 것도 Python 모범 사례입니다.
import os
if not os.path.exists(directory):
os.makedirs(directory)
with open(filepath, 'w') as my_file:
do_stuff(my_file)
그러나 모든 데이터를 동일한 디렉토리에 넣으려고 시도하는 여러 Python 프로세스가 있다고 가정하십시오. 그런 다음 디렉토리 작성에 대한 경합이있을 수 있습니다. 이 경우에는 makedirs
호출을 try-except 블록 으로 감싸는 것이 가장 좋습니다 .
import os
import errno
if not os.path.exists(directory):
try:
os.makedirs(directory)
except OSError as error:
if error.errno != errno.EEXIST:
raise
with open(filepath, 'w') as my_file:
do_stuff(my_file)