Làm thế nào tôi có thể tạo một thư mục lồng nhau một cách an toàn?


4249

Cách thanh lịch nhất để kiểm tra xem thư mục một tệp sẽ được ghi tồn tại hay không, và nếu không, hãy tạo thư mục bằng Python? Đây là những gì tôi đã cố gắng:

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)

Bằng cách nào đó, tôi đã bỏ lỡ os.path.exists(cảm ơn kanja, Blair và Douglas). Đây là những gì tôi có bây giờ:

def ensure_dir(file_path):
    directory = os.path.dirname(file_path)
    if not os.path.exists(directory):
        os.makedirs(directory)

Có một cờ cho "mở", làm cho điều này xảy ra tự động?


27
Nói chung, bạn có thể cần phải tính đến trường hợp không có thư mục trong tên tệp. Trên máy của tôi, dirname ('foo.txt') cho '', không tồn tại và khiến cho makenirs () không thành công.
Brian Hawkins

11
Trong python 2.7 os.path.mkdirkhông tồn tại. Đó là os.mkdir.
drevicko

6
Nếu đường dẫn tồn tại, người ta không chỉ kiểm tra xem đó có phải là thư mục chứ không phải tệp thông thường hoặc đối tượng khác (nhiều câu trả lời kiểm tra này) cũng cần kiểm tra xem nó có thể ghi được không (tôi không tìm thấy câu trả lời nào đã kiểm tra điều này)
phép lạ173

9
Trong trường hợp bạn đến đây để tạo thư mục mẹ của chuỗi đường dẫn tệp p, đây là đoạn mã của tôi:os.makedirs(p[:p.rindex(os.path.sep)], exist_ok=True)
Thamme Gowda

Câu trả lời:


5193

Trên Python ≥ 3.5, sử dụng pathlib.Path.mkdir:

from pathlib import Path
Path("/my/directory").mkdir(parents=True, exist_ok=True)

Đối với các phiên bản cũ hơn của Python, tôi thấy hai câu trả lời có phẩm chất tốt, mỗi câu trả lời có một lỗ hổng nhỏ, vì vậy tôi sẽ đưa ra ý kiến ​​của mình về nó:

Hãy thử os.path.exists, và xem xét os.makedirscho sự sáng tạo.

import os
if not os.path.exists(directory):
    os.makedirs(directory)

Như đã lưu ý trong các bình luận và các nơi khác, có một điều kiện cuộc đua - nếu thư mục được tạo giữa os.path.existscác os.makedirscuộc gọi và cuộc gọi, os.makedirssẽ thất bại với một OSError. Thật không may, việc bắt OSErrorvà tiếp tục chăn không thể đánh lừa được, vì nó sẽ bỏ qua việc không tạo được thư mục do các yếu tố khác, chẳng hạn như không đủ quyền, đĩa đầy đủ, v.v.

Một tùy chọn sẽ là bẫy OSErrorvà kiểm tra mã lỗi được nhúng (xem Có cách nào để lấy thông tin từ nền tảng OSError của Python không ):

import os, errno

try:
    os.makedirs(directory)
except OSError as e:
    if e.errno != errno.EEXIST:
        raise

Ngoài ra, có thể có một giây os.path.exists, nhưng giả sử một thư mục khác đã tạo thư mục sau lần kiểm tra đầu tiên, sau đó xóa nó trước lần thứ hai - chúng ta vẫn có thể bị lừa.

Tùy thuộc vào ứng dụng, mức độ nguy hiểm của các hoạt động đồng thời có thể nhiều hơn hoặc ít hơn mức độ nguy hiểm gây ra bởi các yếu tố khác như quyền truy cập tệp. Nhà phát triển sẽ phải biết nhiều hơn về ứng dụng cụ thể đang được phát triển và môi trường dự kiến ​​của nó trước khi chọn triển khai.

Các phiên bản hiện đại của Python cải thiện mã này khá nhiều, cả bằng cách phơi bày FileExistsError(trong 3.3 +) ...

try:
    os.makedirs("path/to/directory")
except FileExistsError:
    # directory already exists
    pass

... và bằng cách cho phép một đối số từ khóa os.makedirsđược gọiexist_ok (trong 3.2+).

os.makedirs("path/to/directory", exist_ok=True)  # succeeds even if directory exists.

5
Điều kiện cuộc đua là một điểm tốt, nhưng cách tiếp cận trong stackoverflow.com/questions/273192/#273208 , sẽ che dấu một thất bại trong việc tạo thư mục. Đừng cảm thấy tồi tệ khi bỏ phiếu xuống - bạn không thích câu trả lời. Đó là những gì phiếu bầu cho.
Blair Conrad

27
Hãy nhớ rằng os.path.exists () không miễn phí. Nếu trường hợp bình thường là thư mục sẽ ở đó, thì trường hợp không nên xử lý như một ngoại lệ. Nói cách khác, hãy thử mở và ghi vào tệp của bạn, bắt ngoại lệ OSError và, dựa trên errno, thực hiện makenir () của bạn và thử lại hoặc nâng cấp lại. Điều này tạo ra sự trùng lặp mã trừ khi bạn gói văn bản trong một phương thức cục bộ.
Andrew

22
os.path.existscũng trả lại Truecho một tập tin. Tôi đã đăng một câu trả lời để giải quyết điều này.
Acumenus

13
Như các nhà bình luận cho các câu trả lời khác ở đây đã lưu ý, exists_oktham số os.makedirs()có thể được sử dụng để bao quát cách xử lý sự tồn tại trước đó của đường dẫn, kể từ Python 3.2.
Bobble

6
os.mkdirs()có thể tạo các thư mục ngoài ý muốn nếu một dấu tách đường dẫn vô tình bị bỏ sót, thư mục hiện tại không như mong đợi, một phần tử đường dẫn chứa dấu phân cách đường dẫn. Nếu bạn sử dụng os.mkdir()những lỗi này sẽ đưa ra một ngoại lệ, cảnh báo bạn về sự tồn tại của chúng.
drevicko

1241

Python 3,5+:

import pathlib
pathlib.Path('/my/directory').mkdir(parents=True, exist_ok=True) 

pathlib.Path.mkdirnhư được sử dụng ở trên đệ quy tạo thư mục và không đưa ra một ngoại lệ nếu thư mục đã tồn tại. Nếu bạn không cần hoặc muốn cha mẹ được tạo ra, hãy bỏ qua parentsđối số.

Python 3.2+:

Sử dụng pathlib:

Nếu bạn có thể, hãy cài đặt pathlibbackport hiện tại có tên pathlib2. Không cài đặt backport cũ không rõ tên được đặt tên pathlib. Tiếp theo, hãy tham khảo phần Python 3.5+ ở trên và sử dụng nó giống nhau.

Nếu sử dụng Python 3.4, mặc dù nó đi kèm pathlib, nó vẫn thiếu exist_oktùy chọn hữu ích . Backport dự định cung cấp một triển khai mới hơn và vượt trội hơn mkdirbao gồm tùy chọn còn thiếu này.

Sử dụng os:

import os
os.makedirs(path, exist_ok=True)

os.makedirsnhư được sử dụng ở trên đệ quy tạo thư mục và không đưa ra một ngoại lệ nếu thư mục đã tồn tại. Nó exist_okchỉ có đối số tùy chọn nếu sử dụng Python 3.2+, với giá trị mặc định là False. Đối số này không tồn tại trong Python 2.x lên tới 2.7. Như vậy, không cần xử lý ngoại lệ thủ công như với Python 2.7.

Python 2.7 trở lên:

Sử dụng pathlib:

Nếu bạn có thể, hãy cài đặt pathlibbackport hiện tại có tên pathlib2. Không cài đặt backport cũ không rõ tên được đặt tên pathlib. Tiếp theo, hãy tham khảo phần Python 3.5+ ở trên và sử dụng nó giống nhau.

Sử dụng os:

import os
try: 
    os.makedirs(path)
except OSError:
    if not os.path.isdir(path):
        raise

Trong khi một giải pháp ngây thơ có thể lần đầu tiên sử dụng os.path.isdirtiếp theo os.makedirs, giải pháp trên đảo ngược thứ tự của hai cuộc phẫu thuật. Khi làm như vậy, nó ngăn chặn một điều kiện cuộc đua phổ biến phải thực hiện với một nỗ lực trùng lặp trong việc tạo thư mục, và cũng phân tán các tệp từ các thư mục.

Lưu ý rằng việc nắm bắt ngoại lệ và sử dụng errnolà hữu ích hạn chế bởi vì OSError: [Errno 17] File exists, nghĩa là errno.EEXIST, được nêu ra cho cả tệp và thư mục. Nó đáng tin cậy hơn chỉ đơn giản là kiểm tra nếu thư mục tồn tại.

Thay thế:

mkpathtạo thư mục lồng nhau và không làm gì nếu thư mục đã tồn tại. Điều này hoạt động trong cả Python 2 và 3.

import distutils.dir_util
distutils.dir_util.mkpath(path)

Theo Bug 10948 , một hạn chế nghiêm trọng của phương án này là nó chỉ hoạt động một lần trên mỗi quy trình python cho một đường dẫn nhất định. Nói cách khác, nếu bạn sử dụng nó để tạo một thư mục, sau đó xóa thư mục từ bên trong hoặc bên ngoài Python, sau đó sử dụng mkpathlại để tạo lại cùng một thư mục, mkpathsẽ chỉ âm thầm sử dụng thông tin được lưu trong bộ nhớ cache không hợp lệ của nó đã tạo thư mục trước đó và sẽ không thực sự làm cho thư mục một lần nữa. Ngược lại, os.makedirskhông dựa vào bất kỳ bộ đệm như vậy. Hạn chế này có thể ổn đối với một số ứng dụng.


Liên quan đến chế độ của thư mục , vui lòng tham khảo tài liệu nếu bạn quan tâm đến nó.


13
Câu trả lời này bao gồm khá nhiều trường hợp đặc biệt theo như tôi có thể nói. Tôi có kế hoạch gói cái này trong một "nếu không os.path.itorir ()" mặc dù tôi mong thư mục tồn tại gần như mọi lúc và tôi có thể tránh ngoại lệ theo cách đó.
Charles L.

5
@CharlesL. Một ngoại lệ có thể rẻ hơn so với IO của kiểm tra, nếu lý do của bạn là hiệu suất.
jpmc26

1
@ jpmc26 nhưng makenirs không bổ sung stat, umask, lstat khi chỉ kiểm tra để ném OSError.
kwarunek

4
Đây là câu trả lời sai, vì nó giới thiệu một chủng tộc FS tiềm năng. Xem câu trả lời từ Aaron Hall.
ngủ

4
như @saddycal đã nói, điều này chịu một điều kiện chủng tộc tương tự như câu trả lời được chấp nhận. Nếu giữa việc tăng lỗi và kiểm tra os.path.isdirngười khác xóa thư mục, bạn sẽ đưa ra lỗi sai, lỗi thời và khó hiểu mà thư mục đó tồn tại.
trại

604

Sử dụng thử ngoại trừ và mã lỗi đúng từ mô-đun errno sẽ thoát khỏi điều kiện cuộc đua và là nền tảng chéo:

import os
import errno

def make_sure_path_exists(path):
    try:
        os.makedirs(path)
    except OSError as exception:
        if exception.errno != errno.EEXIST:
            raise

Nói cách khác, chúng tôi cố gắng tạo các thư mục, nhưng nếu chúng đã tồn tại, chúng tôi bỏ qua lỗi. Mặt khác, bất kỳ lỗi nào khác được báo cáo. Ví dụ: nếu bạn tạo thư mục 'a' trước đó và xóa tất cả các quyền khỏi nó, bạn sẽ được OSErrornâng lên với errno.EACCES(Quyền bị từ chối, lỗi 13).


24
Câu trả lời được chấp nhận thực sự nguy hiểm vì nó có điều kiện chủng tộc. Tuy nhiên, nó đơn giản hơn, vì vậy nếu bạn không biết về điều kiện cuộc đua hoặc nghĩ rằng nó sẽ không áp dụng cho bạn, đó sẽ là lựa chọn đầu tiên rõ ràng của bạn.
Heikki Toivonen

15
Chỉ tăng ngoại lệ khi exception.errno != errno.EEXISTvô tình bỏ qua trường hợp khi đường dẫn tồn tại nhưng là một đối tượng không phải là thư mục, chẳng hạn như một tệp. Ngoại lệ lý tưởng nên được nêu ra nếu đường dẫn là một đối tượng không phải thư mục.
Acumenus

178
Lưu ý rằng mã trên tương đương vớios.makedirs(path,exist_ok=True)
Navin

58
@Navin exist_okTham số được giới thiệu trong Python 3.2. Nó không có trong Python 2.x. Tôi sẽ kết hợp nó vào câu trả lời của tôi.
Acumenus

26
@HeikkiToivonen Về mặt kỹ thuật, nếu một chương trình khác đang sửa đổi các thư mục và tệp cùng lúc với chương trình của bạn, toàn bộ chương trình của bạn là một điều kiện cuộc đua khổng lồ. Điều gì để ngăn chặn một chương trình khác chỉ xóa thư mục này sau khi mã tạo ra nó và trước khi bạn thực sự đặt các tập tin vào nó?
jpmc26

102

Cá nhân tôi khuyên bạn nên sử dụng os.path.isdir()để kiểm tra thay vì 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

Nếu bạn có:

>>> dir = raw_input(":: ")

Và một đầu vào người dùng ngu ngốc:

:: /tmp/dirname/filename.etc

... Bạn sẽ kết thúc với một thư mục có tên filename.etckhi bạn chuyển đối số đó sang os.makedirs()nếu bạn kiểm tra os.path.exists().


8
Nếu bạn chỉ sử dụng 'isdir', bạn sẽ không gặp vấn đề gì khi bạn cố gắng tạo thư mục và một tệp có cùng tên đã tồn tại?
MrWonderful

3
@MrWonderful Ngoại lệ kết quả khi tạo một thư mục trên một tệp hiện có sẽ phản ánh chính xác vấn đề trở lại cho người gọi.
Damian Yerrick

79

Kiểm tra os.makedirs: (Nó đảm bảo đường dẫn hoàn chỉnh tồn tại.)
Để xử lý thực tế thư mục có thể tồn tại, hãy bắt OSError. (Nếu exist_okFalse(mặc định), an OSErrorđược nâng lên nếu thư mục đích đã tồn tại.)

import os
try:
    os.makedirs('./path/to/somewhere')
except OSError:
    pass

19
với thử / ngoại trừ, bạn sẽ che dấu lỗi trong quá trình tạo thư mục, trong trường hợp thư mục không tồn tại nhưng vì một số lý do bạn không thể thực hiện được
Blair Conrad

3
OSErrorsẽ được nâng lên ở đây nếu đường dẫn là một tệp hoặc thư mục hiện có. Tôi đã đăng một câu trả lời để giải quyết điều này.
Acumenus

4
Đây là một nửa ở đó. Bạn cần kiểm tra tình trạng lỗi phụ OSErrortrước khi quyết định bỏ qua nó. Xem stackoverflow.com/a/5032238/763269 .
Chris Johnson

71

Bắt đầu từ Python 3.5, pathlib.Path.mkdircó một exist_okcờ:

from pathlib import Path
path = Path('/my/directory/filename.txt')
path.parent.mkdir(parents=True, exist_ok=True) 
# path.parent ~ os.path.dirname(path)

Điều này đệ quy tạo thư mục và không đưa ra một ngoại lệ nếu thư mục đã tồn tại.

(giống như os.makedirscó một exist_okcờ bắt đầu từ python 3.2, vd os.makedirs(path, exist_ok=True))


46

Hiểu biết cụ thể về tình huống này

Bạn đưa ra một tệp cụ thể tại một đường dẫn nhất định và bạn kéo thư mục từ đường dẫn tệp. Sau đó, sau khi chắc chắn rằng bạn có thư mục, bạn cố gắng mở một tệp để đọc. Để bình luận về mã này:

filename = "/my/directory/filename.txt"
dir = os.path.dirname(filename)

Chúng tôi muốn tránh ghi đè chức năng dựng sẵn , dir. Ngoài ra, filepathhoặc có lẽ fullfilepathlà một tên ngữ nghĩa tốt hơn filenamevì vậy điều này sẽ được viết tốt hơn:

import os
filepath = '/my/directory/filename.txt'
directory = os.path.dirname(filepath)

Mục tiêu cuối cùng của bạn là mở tệp này, ban đầu bạn nêu, để viết, nhưng về cơ bản bạn đang tiếp cận mục tiêu này (dựa trên mã của bạn) như thế này, mở tệp để đọc :

if not os.path.exists(directory):
    os.makedirs(directory)
f = file(filename)

Giả sử mở để đọc

Tại sao bạn tạo một thư mục cho một tập tin mà bạn mong đợi ở đó và có thể đọc được?

Chỉ cần cố gắng để mở tập tin.

with open(filepath) as my_file:
    do_stuff(my_file)

Nếu thư mục hoặc tệp không có ở đó, bạn sẽ nhận được một IOErrorsố lỗi liên quan: errno.ENOENTsẽ trỏ đến số lỗi chính xác bất kể nền tảng của bạn. Bạn có thể bắt nó nếu bạn muốn, ví dụ:

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

Giả sử chúng ta đang mở để viết

Đây có lẽ là những gì bạn muốn.

Trong trường hợp này, chúng tôi có lẽ không phải đối mặt với bất kỳ điều kiện chủng tộc. Vì vậy, chỉ cần làm như bạn đã được, nhưng lưu ý rằng để viết, bạn cần mở bằng wchế độ (hoặc ađể chắp thêm). Đây cũng là cách tốt nhất để sử dụng trình quản lý bối cảnh để mở tệp.

import os
if not os.path.exists(directory):
    os.makedirs(directory)
with open(filepath, 'w') as my_file:
    do_stuff(my_file)

Tuy nhiên, giả sử chúng tôi có một số quy trình Python cố gắng đưa tất cả dữ liệu của họ vào cùng một thư mục. Sau đó, chúng tôi có thể có tranh chấp về việc tạo ra các thư mục. Trong trường hợp đó, tốt nhất là kết thúc makedirscuộc gọi trong một khối ngoại trừ thử.

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)

34

Hãy thử os.path.existschức năng

if not os.path.exists(dir):
    os.mkdir(dir)

3
Tôi sẽ bình luận về câu hỏi, nhưng chúng tôi có nghĩa là os.mkdir? Con trăn của tôi (2.5.2) không có os.path.mkdir ....
Blair Conrad

1
Không có os.path.mkdir()phương pháp. mô đun os.path thực hiện một số chức năng hữu ích trên tên đường dẫn .
Serge S.

31

Tôi đã đặt như sau. Nó không hoàn toàn ngu ngốc mặc dù.

import os

dirname = 'create/me'

try:
    os.makedirs(dirname)
except OSError:
    if os.path.exists(dirname):
        # We are nearly safe
        pass
    else:
        # There was an error on creation, so make sure we know about it
        raise

Như tôi nói, điều này không thực sự dễ hiểu, bởi vì chúng ta có khả năng không tạo được thư mục và một quy trình khác tạo ra nó trong giai đoạn đó.



Hai vấn đề: (1) bạn cần kiểm tra tình trạng lỗi phụ của OSError trước khi quyết định kiểm tra os.path.exists- xem stackoverflow.com/a/5032238/763269 và (2) thành công os.path.existskhông có nghĩa là thư mục tồn tại, chỉ là đường dẫn tồn tại tồn tại - có thể là một tệp, hoặc một liên kết tượng trưng hoặc đối tượng hệ thống tệp khác.
Chris Johnson

24

Kiểm tra nếu một thư mục tồn tại và tạo nó nếu cần thiết?

Câu trả lời trực tiếp cho vấn đề này là, giả sử một tình huống đơn giản mà bạn không mong đợi người dùng hoặc quy trình khác sẽ gây rối với thư mục của mình:

if not os.path.exists(d):
    os.makedirs(d)

hoặc nếu làm cho thư mục tuân theo các điều kiện chủng tộc (nghĩa là nếu sau khi kiểm tra đường dẫn tồn tại, một cái gì đó khác có thể đã được thực hiện) làm điều này:

import errno
try:
    os.makedirs(d)
except OSError as exception:
    if exception.errno != errno.EEXIST:
        raise

Nhưng có lẽ một cách tiếp cận thậm chí tốt hơn là vượt qua vấn đề tranh chấp tài nguyên, bằng cách sử dụng các thư mục tạm thời thông qua tempfile:

import tempfile

d = tempfile.mkdtemp()

Đây là những điều cần thiết từ tài liệu trực tuyến:

mkdtemp(suffix='', prefix='tmp', dir=None)
    User-callable function to create and return a unique temporary
    directory.  The return value is the pathname of the directory.

    The directory is readable, writable, and searchable only by the
    creating user.

    Caller is responsible for deleting the directory when done with it.

Mới trong Python 3.5: pathlib.Pathvớiexist_ok

Có một Pathđối tượng mới (kể từ 3,4) với rất nhiều phương thức người ta muốn sử dụng với các đường dẫn - một trong số đó là mkdir.

(Đối với ngữ cảnh, tôi đang theo dõi đại diện hàng tuần của mình bằng một tập lệnh. Đây là các phần mã có liên quan từ tập lệnh cho phép tôi tránh nhấn Stack Overflow hơn một lần mỗi ngày cho cùng một dữ liệu.)

Đầu tiên là hàng nhập khẩu có liên quan:

from pathlib import Path
import tempfile

Chúng ta không phải đối phó với os.path.joinbây giờ - chỉ cần tham gia các phần đường dẫn với /:

directory = Path(tempfile.gettempdir()) / 'sodata'

Sau đó, tôi tạm thời đảm bảo thư mục tồn tại - exist_okđối số hiển thị trong Python 3.5:

directory.mkdir(exist_ok=True)

Đây là phần có liên quan của tài liệu :

Nếu exist_oklà đúng, các FileExistsErrorngoại lệ sẽ bị bỏ qua (hành vi tương tự như POSIX mkdir -plệnh), nhưng chỉ khi thành phần đường dẫn cuối cùng không phải là tệp không có thư mục hiện có.

Đây là một chút về kịch bản - trong trường hợp của tôi, tôi không phải chịu điều kiện chủng tộc, tôi chỉ có một quy trình hy vọng thư mục (hoặc tệp chứa) sẽ ở đó và tôi không có bất cứ điều gì cố gắng xóa cac thu mục.

todays_file = directory / str(datetime.datetime.utcnow().date())
if todays_file.exists():
    logger.info("todays_file exists: " + str(todays_file))
    df = pd.read_json(str(todays_file))

Pathcác đối tượng phải được ép buộc strtrước các API khác mong muốn strcác đường dẫn có thể sử dụng chúng.

Có lẽ Pandas nên được cập nhật để chấp nhận các thể hiện của lớp cơ sở trừu tượng , os.PathLike.


20

Trong Python 3.4, bạn cũng có thể sử dụng mô-đun hoàn toàn mớipathlib :

from pathlib import Path
path = Path("/my/directory/filename.txt")
try:
    if not path.parent.exists():
        path.parent.mkdir(parents=True)
except OSError:
    # handle error; you can also catch specific errors like
    # FileExistsError and so on.

@JanuszSkonieczny pypi.python.org/pypi/pathlib2 là backport mới hơn. Người lớn tuổi hơn không rõ.
Acumenus

Như đã nêu trong dòng đầu tiên của readme; P. Nhưng backport cũ vẫn còn hiệu lực cho câu trả lời ở đây. Và không có đau đầu đặt tên. Không cần phải giải thích tại sao và khi nào nên sử dụng pathlibvà ở đâu pathlib2cho người dùng mới và tôi nghĩ rằng ưu điểm ở đây sẽ tìm ra sự phản đối;)
Janusz Skonieczny

13

Các tài liệu liên quan Python cho thấy việc sử dụng các EAFP mã hóa phong cách (dễ dàng hơn để hỏi cho Tha thứ hơn Permission) . Điều này có nghĩa là mã

try:
    os.makedirs(path)
except OSError as exception:
    if exception.errno != errno.EEXIST:
        raise
    else:
        print "\nBE CAREFUL! Directory %s already exists." % path

tốt hơn so với giải pháp thay thế

if not os.path.exists(path):
    os.makedirs(path)
else:
    print "\nBE CAREFUL! Directory %s already exists." % path

Các tài liệu cho thấy điều này chính xác vì điều kiện cuộc đua được thảo luận trong câu hỏi này. Ngoài ra, như những người khác đề cập ở đây, có một lợi thế về hiệu năng khi truy vấn một lần thay vì hai lần HĐH. Cuối cùng, đối số được đặt phía trước, có khả năng, có lợi cho mã thứ hai trong một số trường hợp - khi nhà phát triển biết môi trường mà ứng dụng đang chạy - chỉ có thể được ủng hộ trong trường hợp đặc biệt là chương trình đã thiết lập môi trường riêng cho chính nó (và các trường hợp khác của cùng một chương trình).

Ngay cả trong trường hợp đó, đây là một thực tiễn xấu và có thể dẫn đến việc gỡ lỗi vô ích lâu dài. Ví dụ: thực tế chúng tôi đặt quyền cho một thư mục không nên để lại cho chúng tôi các quyền hiển thị được đặt phù hợp cho mục đích của chúng tôi. Một thư mục cha có thể được gắn với các quyền khác. Nói chung, một chương trình phải luôn hoạt động chính xác và lập trình viên không nên mong đợi một môi trường cụ thể.


11

Trong Python3 , os.makedirshỗ trợ cài đặt exist_ok. Cài đặt mặc định là False, có nghĩa là OSErrorsẽ được nâng lên nếu thư mục đích đã tồn tại. Bằng cách đặt exist_okthành True, OSError(thư mục tồn tại) sẽ bị bỏ qua và thư mục sẽ không được tạo.

os.makedirs(path,exist_ok=True)

Trong Python2 , os.makedirskhông hỗ trợ cài đặt exist_ok. Bạn có thể sử dụng cách tiếp cận trong câu trả lời của heikki-toivonen :

import os
import errno

def make_sure_path_exists(path):
    try:
        os.makedirs(path)
    except OSError as exception:
        if exception.errno != errno.EEXIST:
            raise

11

Đối với giải pháp một lớp lót, bạn có thể sử dụng IPython.utils.path.ensure_dir_exists():

from IPython.utils.path import ensure_dir_exists
ensure_dir_exists(dir)

Từ tài liệu : Đảm bảo rằng một thư mục tồn tại. Nếu nó không tồn tại, hãy thử tạo nó và bảo vệ chống lại tình trạng chủng tộc nếu một quá trình khác đang làm như vậy.


Tài liệu IPython mới có sẵn ở đây .
jkdev

3
Các IPythonmô-đun là hoàn toàn không đảm bảo để có mặt. Nó thực sự có mặt trên máy Mac của tôi, nhưng không có trên bất kỳ bản cài đặt Linux nào của tôi. Về cơ bản, nó không phải là một trong những mô-đun được liệt kê trong Chỉ mục mô-đun Python .
Acumenus

1
Chắc chắn rồi. Để cài đặt gói, chỉ cần chạy bình thường pip install ipythonhoặc bao gồm các sự phụ thuộc vào bạn requirements.txt hoặc pom.xml . Tài liệu: ipython.org/install.html
tashuhka

9

Bạn có thể dùng mkpath

# Create a directory and any missing ancestor directories. 
# If the directory already exists, do nothing.

from distutils.dir_util import mkpath
mkpath("test")    

Lưu ý rằng nó sẽ tạo các thư mục tổ tiên là tốt.

Nó hoạt động cho Python 2 và 3.


2
distutils.dir_utilkhông phải là một phần của API công khai distutil và có vấn đề trong môi trường đa luồng: bug.python.org/su10948
Pod

1
Đúng. Như đã lưu ý trong thông báo đầu tiên về lỗi, vấn đề distutils.dir_util.mkpathlà nếu bạn tạo một thư mục, sau đó xóa nó từ bên trong hoặc bên ngoài Python, sau đó sử dụng mkpathlại, mkpathsẽ chỉ sử dụng thông tin được lưu trong bộ nhớ cache không hợp lệ của nó khi đã tạo thư mục trước đó và sẽ không thực sự làm cho thư mục một lần nữa. Ngược lại, os.makedirskhông dựa vào bất kỳ bộ đệm như vậy.
Acumenus

8

Tôi sử dụng os.path.exists(), đây là một tập lệnh Python 3 có thể được sử dụng để kiểm tra xem một thư mục có tồn tại không, tạo một tập lệnh nếu nó không tồn tại và xóa nó nếu nó tồn tại (nếu muốn).

Nó nhắc người dùng nhập liệu của thư mục và có thể dễ dàng sửa đổi.


6

Bạn có thể sử dụng os.listdircho việc này:

import os
if 'dirName' in os.listdir('parentFolderPath')
    print('Directory Exists')

Điều này không trả lời câu hỏi
Georgy

6

Tôi đã tìm thấy Q / A này và ban đầu tôi cảm thấy bối rối trước một số thất bại và lỗi tôi đang mắc phải. Tôi đang làm việc trong Python 3 (v.3.5 trong môi trường ảo Anaconda trên hệ thống Arch Linux x86_64).

Xem xét cấu trúc thư mục này:

└── output/         ## dir
   ├── corpus       ## file
   ├── corpus2/     ## dir
   └── subdir/      ## dir

Dưới đây là các thí nghiệm / ghi chú của tôi, trong đó làm rõ mọi thứ:

# ----------------------------------------------------------------------------
# [1] /programming/273192/how-can-i-create-a-directory-if-it-does-not-exist

import pathlib

""" Notes:
        1.  Include a trailing slash at the end of the directory path
            ("Method 1," below).
        2.  If a subdirectory in your intended path matches an existing file
            with same name, you will get the following error:
            "NotADirectoryError: [Errno 20] Not a directory:" ...
"""
# Uncomment and try each of these "out_dir" paths, singly:

# ----------------------------------------------------------------------------
# METHOD 1:
# Re-running does not overwrite existing directories and files; no errors.

# out_dir = 'output/corpus3'                ## no error but no dir created (missing tailing /)
# out_dir = 'output/corpus3/'               ## works
# out_dir = 'output/corpus3/doc1'           ## no error but no dir created (missing tailing /)
# out_dir = 'output/corpus3/doc1/'          ## works
# out_dir = 'output/corpus3/doc1/doc.txt'   ## no error but no file created (os.makedirs creates dir, not files!  ;-)
# out_dir = 'output/corpus2/tfidf/'         ## fails with "Errno 20" (existing file named "corpus2")
# out_dir = 'output/corpus3/tfidf/'         ## works
# out_dir = 'output/corpus3/a/b/c/d/'       ## works

# [2] https://docs.python.org/3/library/os.html#os.makedirs

# Uncomment these to run "Method 1":

#directory = os.path.dirname(out_dir)
#os.makedirs(directory, mode=0o777, exist_ok=True)

# ----------------------------------------------------------------------------
# METHOD 2:
# Re-running does not overwrite existing directories and files; no errors.

# out_dir = 'output/corpus3'                ## works
# out_dir = 'output/corpus3/'               ## works
# out_dir = 'output/corpus3/doc1'           ## works
# out_dir = 'output/corpus3/doc1/'          ## works
# out_dir = 'output/corpus3/doc1/doc.txt'   ## no error but creates a .../doc.txt./ dir
# out_dir = 'output/corpus2/tfidf/'         ## fails with "Errno 20" (existing file named "corpus2")
# out_dir = 'output/corpus3/tfidf/'         ## works
# out_dir = 'output/corpus3/a/b/c/d/'       ## works

# Uncomment these to run "Method 2":

#import os, errno
#try:
#       os.makedirs(out_dir)
#except OSError as e:
#       if e.errno != errno.EEXIST:
#               raise
# ----------------------------------------------------------------------------

Kết luận: theo tôi, "Phương pháp 2" mạnh mẽ hơn.

[1] Làm cách nào để tạo thư mục nếu nó không tồn tại?

[2] https://docs.python.org/3/l Library / os.html # os.makenirs


6

Tôi thấy câu trả lời của Heikki ToivonenABB và nghĩ về sự thay đổi này.

import os
import errno

def make_sure_path_exists(path):
    try:
        os.makedirs(path)
    except OSError as exception:
        if exception.errno != errno.EEXIST or not os.path.isdir(path):
            raise


5

Tại sao không sử dụng mô đun quy trình con nếu chạy trên máy có hỗ trợ lệnh mkdirvới -ptùy chọn? Hoạt động trên python 2.7 và python 3.6

from subprocess import call
call(['mkdir', '-p', 'path1/path2/path3'])

Nên làm thủ thuật trên hầu hết các hệ thống.

Trong trường hợp tính di động không thành vấn đề (ví dụ, sử dụng docker), giải pháp là 2 dòng sạch. Bạn cũng không phải thêm logic để kiểm tra xem thư mục có tồn tại hay không. Cuối cùng, an toàn để chạy lại mà không có bất kỳ tác dụng phụ nào

Nếu bạn cần xử lý lỗi:

from subprocess import check_call
try:
    check_call(['mkdir', '-p', 'path1/path2/path3'])
except:
    handle...

4

Nếu bạn xem xét những điều sau đây:

os.path.isdir('/tmp/dirname')

có nghĩa là một thư mục (đường dẫn) tồn tại VÀ là một thư mục. Vì vậy, đối với tôi cách này làm những gì tôi cần. Vì vậy, tôi có thể chắc chắn rằng đó là thư mục (không phải là một tập tin) và tồn tại.


Làm thế nào để trả lời một câu hỏi về việc tạo một thư mục?
Georgy

3

Gọi hàm create_dir()tại điểm vào của chương trình / dự án của bạn.

import os

def create_dir(directory):
    if not os.path.exists(directory):
        print('Creating Directory '+directory)
        os.makedirs(directory)

create_dir('Project directory')

3

Bạn phải đặt đường dẫn đầy đủ trước khi tạo thư mục:

import os,sys,inspect
import pathlib

currentdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
your_folder = currentdir + "/" + "your_folder"

if not os.path.exists(your_folder):
   pathlib.Path(your_folder).mkdir(parents=True, exist_ok=True)

Điều này làm việc cho tôi và hy vọng, nó cũng sẽ làm việc cho bạn


1
import os
if os.path.isfile(filename):
    print "file exists"
else:
    "Your code here"

Mã của bạn ở đây sử dụng lệnh (chạm)

Điều này sẽ kiểm tra xem tập tin có ở đó không nếu nó sẽ tạo ra nó.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.