检查要写入文件的目录是否存在的最优雅方法是什么,如果不存在,则使用Python创建目录?以下是我的尝试:
1 2 3 4 5 6 7 8 9 10 11 | 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) |
不知怎么的,我错过了(感谢kanja、Blair和Douglas)。这就是我现在所拥有的:
1 2 3 4 | def ensure_dir(file_path): directory = os.path.dirname(file_path) if not os.path.exists(directory): os.makedirs(directory) |
是否有一个"打开"的标志,使这一切自动发生?
我看到了两个有优点的答案,每个都有一个小缺点,所以我将给出我的看法:
尝试
1 2 3 | import os if not os.path.exists(directory): os.makedirs(directory) |
正如在评论和其他地方所指出的,有一个比赛条件–如果在
一种选择是捕获
1 2 3 4 5 6 7 | import os, errno try: os.makedirs(directory) except OSError as e: if e.errno != errno.EEXIST: raise |
或者,可以有第二个
根据应用程序的不同,并发操作的危险可能大于或小于文件权限等其他因素造成的危险。在选择实现之前,开发人员必须对正在开发的特定应用程序及其预期环境有更多的了解。
Python的现代版本在很大程度上改进了这段代码,都是通过在3.3+中公开
1 2 3 4 5 | try: os.makedirs("path/to/directory") except FileExistsError: # directory already exists pass |
…并允许一个关键字参数
1 | os.makedirs("path/to/directory", exist_ok=True) # succeeds even if directory exists. |
Python 3.5 +:
1 2 | import pathlib pathlib.Path('/my/directory').mkdir(parents=True, exist_ok=True) |
使用
如果可以,安装当前名为
如果使用Python 3.4,即使它带有
使用
1 2 | import os os.makedirs(path, exist_ok=True) |
上面使用的
使用
如果可以,安装当前名为
使用
1 2 3 4 5 6 | import os try: os.makedirs(path) except OSError: if not os.path.isdir(path): raise |
虽然一个简单的解决方案可能首先使用
注意,捕获异常并使用
选择:
1 2 | import distutils.dir_util distutils.dir_util.mkpath(path) |
对于每个Bug 10948,这种方法的一个严重限制是,对于给定的路径,它只能在每个python进程中工作一次。换句话说,如果你用它来创建一个目录,然后从内部或外部Python删除目录,然后使用
关于目录的模式,如果您关心的话,请参考文档。
使用try except和正确的错误代码从errno模块摆脱竞争条件,是跨平台的:
1 2 3 4 5 6 7 8 9 | 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'并从中删除所有权限,您将得到一个
我个人建议您使用
1 2 3 4 5 6 7 8 | >>> 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 |
如果你有:
1 | >>> dir = raw_input("::") |
以及一个愚蠢的用户输入:
1 | :: /tmp/dirname/filename.etc |
…如果使用
检查操作系统。makedirs:(它确保存在完整的路径。)要处理目录可能存在的事实,请捕获OSError。(如果exist_ok为False(缺省值),如果目标目录已经存在,则会引发OSError。)
1 2 3 4 5 | import os try: os.makedirs('./path/to/somewhere') except OSError: pass |
从Python 3.5开始,
1 2 3 4 | from pathlib import Path path = Path('/my/directory/filename.txt') path.parent.mkdir(parents=True, exist_ok=True) # path.parent ~ os.path.dirname(path) |
这将递归地创建目录,如果目录已经存在,则不会引发异常。
(就像
洞察这种情况的具体情况
您在特定路径上给出一个特定的文件,然后从文件路径中提取目录。然后,在确保您拥有目录之后,您尝试打开一个文件以供读取。要对本守则作出评论:
1
2 filename ="/my/directory/filename.txt"
dir = os.path.dirname(filename)
我们希望避免覆盖内置函数
1 2 3 | import os filepath = '/my/directory/filename.txt' directory = os.path.dirname(filepath) |
你的最终目标是打开这个文件,你最初的状态是写,但你实际上是在接近这个目标(基于你的代码),就像这样,打开文件阅读:
1
2
3 if not os.path.exists(directory):
os.makedirs(directory)
f = file(filename)
假设打开读取
为什么要为期望存在并能够读取的文件创建目录呢?
试着打开文件。
1 2 | with open(filepath) as my_file: do_stuff(my_file) |
如果目录或文件不在那里,您将得到一个
1 2 3 4 5 6 7 8 9 | 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 |
假设我们开始写
这可能就是你想要的。
在这种情况下,我们可能没有面临任何竞争条件。因此,就像您刚才所做的那样,但是请注意,对于编写,您需要使用
1 2 3 4 5 | import os if not os.path.exists(directory): os.makedirs(directory) with open(filepath, 'w') as my_file: do_stuff(my_file) |
但是,假设我们有几个Python进程试图将它们的所有数据放到同一个目录中。然后我们可能会对目录的创建产生争用。在这种情况下,最好将
1 2 3 4 5 6 7 8 9 10 | 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) |
尝试
1 2 | if not os.path.exists(dir): os.mkdir(dir) |
我把下面的记下来了。不过,这也不是万无一失的。
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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 |
就像我说的,这并不是万无一失的,因为我们有可能无法创建目录,而另一个进程在此期间创建目录。
Check if a directory exists and create it if necessary?
直接的答案是,假设一个简单的情况,您不希望其他用户或进程打乱您的目录:
1 2 | if not os.path.exists(d): os.makedirs(d) |
或者如果创建目录受竞态条件约束(也就是说,在检查路径是否存在之后,可能已经有其他东西创建了它),则执行以下操作:
1 2 3 4 5 6 | import errno try: os.makedirs(d) except OSError as exception: if exception.errno != errno.EEXIST: raise |
但是,也许一个更好的方法是避开资源争用问题,通过
1 2 3 | import tempfile d = tempfile.mkdtemp() |
以下是在线文档的要点:
1
2
3
4
5
6
7
8 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.
New in Python 3.5:
有一个新的
(说到上下文,我用一个脚本跟踪我的每周代表。下面是脚本中的相关代码部分,这些代码允许我避免每天对相同的数据进行多次堆栈溢出。)
首先是相关进口:
1 2 | from pathlib import Path import tempfile |
我们现在不需要处理
1 | directory = Path(tempfile.gettempdir()) / 'sodata' |
然后我要确保目录存在——Python 3.5中出现了
1 | directory.mkdir(exist_ok=True) |
以下是文档的相关部分:
If
exist_ok is true,FileExistsError exceptions will be ignored (same behavior as thePOSIX mkdir -p command), but only if the last path component is not an existing non-directory file.
下面是更多的脚本—在我的例子中,我不受竞态条件的约束,我只有一个进程期望目录(或包含的文件)在那里,并且没有任何东西试图删除目录。
1 2 3 4 | 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)) |
也许应该更新panda以接受抽象基类
在Python 3.4中,您还可以使用全新的
1 2 3 4 5 6 7 8 | 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. |
相关的Python文档建议使用EAFP编码风格(请求原谅比请求许可更容易)。这意味着代码
1 2 3 4 5 6 7 8 | try: os.makedirs(path) except OSError as exception: if exception.errno != errno.EEXIST: raise else: print" BE CAREFUL! Directory %s already exists." % path |
比其他选择更好吗
1 2 3 4 5 | if not os.path.exists(path): os.makedirs(path) else: print" BE CAREFUL! Directory %s already exists." % path |
文档表明这正是由于这个问题中讨论的竞态条件。此外,正如其他人在这里提到的,查询一次而不是两次操作系统具有性能优势。最后,论证放置,可能赞成第二个代码在某些情况下,当开发人员知道应用程序运行环境,只能提倡在特殊情况下,该项目已经成立了一个私人环境本身(以及其他相同的实例程序)。
即使在这种情况下,这也是一个糟糕的实践,可能导致长时间无用的调试。例如,我们为目录设置权限的事实不应该给我们留下这样的印象:权限的设置适合我们的目的。可以使用其他权限挂载父目录。一般来说,程序应该总是正确地工作,程序员不应该期望一个特定的环境。
在Python3中,
1 | os.makedirs(path,exist_ok=True) |
在Python2中,
1 2 3 4 5 6 7 8 9 | import os import errno def make_sure_path_exists(path): try: os.makedirs(path) except OSError as exception: if exception.errno != errno.EEXIST: raise |
您可以使用
1 2 3 4 5 | # Create a directory and any missing ancestor directories. # If the directory already exists, do nothing. from distutils.dir_util import mkpath mkpath("test") |
注意,它还将创建祖先目录。
它适用于python2和python3。
我使用
它提示用户输入目录,可以很容易地修改。
对于单行解决方案,您可以使用
1 2 | from IPython.utils.path import ensure_dir_exists ensure_dir_exists(dir) |
从文档中:确保存在目录。如果它不存在,则尝试创建它,并在另一个进程执行相同操作时防止竞争条件。
你可以用
1 2 3 | import os if 'dirName' in os.listdir('parentFolderPath') print('Directory Exists') |
在处理文件I/O时,要考虑的重要事情是
TOCTTOU(检查到使用时间)因此,使用
1 2 3 4 5 | try: os.makedirs(dir_path) except OSError as e: if e.errno != errno.EEXIS: raise |
我发现了这个Q/A,一开始我对我得到的一些失败和错误感到困惑。我正在使用Python 3 (v3.5在Arch Linux x86_64系统上的Anaconda虚拟环境中工作)。
考虑这个目录结构:
1 2 3 4 | └── output/ ## dir ├── corpus ## file ├── corpus2/ ## dir └── subdir/ ## dir |
以下是我的实验/笔记,它可以澄清一些事情:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | # ---------------------------------------------------------------------------- # [1] https://stackoverflow.com/questions/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 # ---------------------------------------------------------------------------- |
结论:在我看来,"方法2"更稳健。
如果目录不存在,我如何创建它?
[2]https://docs.python.org/3/library/os.html os.makedirs
我看到了海基·托伊沃宁和A-B-B的答案,想到了这种变化。
1 2 3 4 5 6 7 8 9 | 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 |
如果你考虑以下几点:
1 | os.path.isdir('/tmp/dirname') |
表示存在一个目录(路径),并且是一个目录。所以对我来说,这样做是我所需要的。所以我可以确保它是文件夹(而不是文件)并且存在。
如果运行在支持shell语言的机器上,为什么不使用子进程模块呢?在python 2.7和python 3.6上工作
1 2 | from subprocess import call call(['mkdir', '-p', 'path1/path2/path3']) |
应该对大多数系统都有效。
在程序/项目的入口点调用函数
1 2 3 4 5 6 7 8 | import os def create_dir(directory): if not os.path.exists(directory): print('Creating Directory '+directory) os.makedirs(directory) create_dir('Project directory') |
使用此命令检查并创建dir
1 2 | if not os.path.isdir(test_img_dir): os.mkdir(str("./"+test_img_dir)) |
1 2 3 4 5 | import os if os.path.isfile(filename): print"file exists" else: "Your code here" |
Where your code here is use the (touch) command
这将检查文件是否在那里,如果没有,那么它将创建它。