如何安全地创建嵌套目录? ゞ 浴缸里的玫瑰 2024-03-31 16:51 34阅读 0赞 ## 问题描述: ## 如何检查要写入文件的目录是否存在,如果不存在,则使用 Python 创建目录? > HuntsBot周刊–不定时分享成功产品案例,学习他们如何成功建立自己的副业–huntsbot.com ## 解决方案1: ## > huntsbot.com聚合了超过10+全球外包任务平台的外包需求,寻找外包任务与机会变的简单与高效。 在 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 并检查嵌入的错误代码(请参阅 Is there a cross-platform way of getting information from Python’s 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 …并通过允许 a keyword argument to os.makedirs called exist\_ok(在 3.2+ 中)。 os.makedirs("path/to/directory", exist_ok=True) # succeeds even if directory exists. `竞争条件很好,但 stackoverflow.com/questions/273192/#273208 中的方法将掩盖创建目录的失败。不要因为投反对票而感到难过——你不喜欢这个答案。这就是投票的目的。` `请记住 os.path.exists() 不是免费的。如果正常情况是目录会存在,那么不存在的情况应作为异常处理。换句话说,尝试打开并写入您的文件,捕获 OSError 异常,并根据 errno 执行您的 makedir() 并重新尝试或重新引发。这会造成代码重复,除非您将编写内容包装在本地方法中。` `os.path.exists 还为文件返回 True。我已经发布了一个答案来解决这个问题。` `正如此处其他答案的评论者所指出的,自 Python 3.2 以来,os.makedirs() 的 exists_ok 参数可用于涵盖如何处理路径的先前存在。` `如果路径分隔符被意外遗漏,os.mkdirs() 可能会创建意外文件夹,当前文件夹与预期不符,路径元素包含路径分隔符。如果您使用 os.mkdir(),这些错误将引发异常,提醒您它们的存在。` ## 解决方案2: ## > huntsbot.com – 高效赚钱,自由工作 Python 3.5+: import pathlib pathlib.Path('/my/directory').mkdir(parents=True, exist_ok=True) 上面使用的 pathlib.Path.mkdir 递归地创建目录,如果目录已经存在,则不会引发异常。如果您不需要或不希望创建父级,请跳过 parents 参数。 Python 3.2+: 使用 pathlib: 如果可以,请安装名为 pathlib2 的当前 pathlib 反向端口。不要安装名为 pathlib 的较旧的未维护反向端口。接下来,参考上面的 Python 3.5+ 部分,同样使用它。 如果使用 Python 3.4,即使它带有 pathlib,它也缺少有用的 exist\_ok 选项。向后移植旨在提供一个更新的、更高级的 mkdir 实现,其中包括这个缺失的选项。 使用 os: import os os.makedirs(path, exist_ok=True) 上面使用的 os.makedirs 递归地创建目录,如果目录已经存在,则不会引发异常。只有在使用 Python 3.2+ 时,它才有可选的 exist\_ok 参数,默认值为 False。此参数在 Python 2.x 到 2.7 中不存在。因此,不需要像 Python 2.7 那样手动处理异常。 Python 2.7+: 使用 pathlib: 如果可以,请安装名为 pathlib2 的当前 pathlib 反向端口。不要安装名为 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) 根据 Bug 10948,此替代方案的一个严重限制是它对于给定路径的每个 python 进程仅工作一次。换句话说,如果您使用它创建一个目录,然后从 Python 内部或外部删除该目录,然后再次使用 mkpath 重新创建相同的目录,mkpath 将简单地使用其先前创建的无效缓存信息目录,并且实际上不会再次创建该目录。相反,os.makedirs 不依赖任何此类缓存。对于某些应用程序,此限制可能没问题。 关于目录的模式,如果你关心,请参考文档。 `据我所知,这个答案几乎涵盖了所有特殊情况。我计划将其包装在“if not os.path.isdir()”中,因为我希望该目录几乎每次都存在,并且我可以通过这种方式避免异常。` `@CharlesL。如果您的原因是性能,则异常可能比检查的磁盘 IO 便宜。` `@jpmc26 但 makedirs 在仅检查抛出 OSError 时会执行额外的 stat、umask、lstat。` `这是错误的答案,因为它引入了潜在的 FS 种族条件。请参阅 Aaron Hall 的回答。` `正如@sleepycal 所说,这与接受的答案有类似的竞争条件。如果在引发错误和检查 os.path.isdir 之间其他人删除了该文件夹,您将引发该文件夹存在的错误、过时和令人困惑的错误。` ## 解决方案3: ## > huntsbot.com – 高效赚钱,自由工作 使用 try except 和来自 errno 模块的正确错误代码摆脱了竞争条件并且是跨平台的: 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’ 并从中删除所有权限,您将收到一个 errno.EACCES 引发的 OSError(权限被拒绝,错误 13)。 `接受的答案实际上是危险的,因为它具有竞争条件。不过,它更简单,所以如果你不知道比赛条件,或者认为它不适用于你,那显然是你的首选。` `仅当 exception.errno != errno.EEXIST 会无意中忽略路径存在但为非目录对象(例如文件)时的情况,才引发异常。如果路径是非目录对象,则理想情况下应该引发异常。` `请注意,上面的代码等价于 os.makedirs(path,exist_ok=True)` `@Navin exist_ok 参数是在 Python 3.2 中引入的。它在 Python 2.x 中不存在。我会将其纳入我的答案中。` `@HeikkiToivonen 从技术上讲,如果另一个程序正在修改您的程序的目录和文件,那么您的整个程序就是一个巨大的竞争条件。在代码创建它之后和实际将文件放入其中之前,如何阻止另一个程序删除该目录?` ## 解决方案4: ## > huntsbot.com精选全球7大洲远程工作机会,涵盖各领域,帮助想要远程工作的数字游民们能更精准、更高效的找到对方。 从 Python 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) 这会递归地创建目录,如果目录已经存在,则不会引发异常。 (就像 os.makedirs 从 python 3.2 开始得到一个 exist\_ok 标志,例如 os.makedirs(path, exist\_ok=True)) 注意:当我发布此答案时,没有提到其他答案exist\_ok … ## 解决方案5: ## > huntsbot.com高效搞钱,一站式跟进超10+任务平台外包需求 我个人建议您使用 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 …如果您使用 os.path.exists() 进行测试,当您将该参数传递给 os.makedirs() 时,您最终会得到一个名为 filename.etc 的目录。 ## 解决方案6: ## > huntsbot.com – 程序员副业首选,一站式外包任务、远程工作、创意产品分享订阅平台。 检查 os.makedirs:(它确保完整路径存在。) 要处理目录可能存在的事实,请捕获 OSError。 (如果 exist\_ok 是 False(默认值),如果目标目录已经存在,则会引发 OSError。) import os try: os.makedirs('./path/to/somewhere') except OSError: pass `使用 try/except,您将掩盖目录创建中的错误,如果目录不存在但由于某种原因您无法创建它` ## 解决方案7: ## > huntsbot.com汇聚了国内外优秀的初创产品创意,可按收入、分类等筛选,希望这些产品与实践经验能给您带来灵感。 试试 os.path.exists 函数 if not os.path.exists(dir): os.mkdir(dir) ## 解决方案8: ## > 保持自己快人一步,享受全网独家提供的一站式外包任务、远程工作、创意产品订阅服务–huntsbot.com 关于这种情况的具体情况的见解 您在特定路径中提供特定文件,然后从文件路径中提取目录。然后在确保您拥有该目录之后,您尝试打开一个文件进行读取。要评论此代码: 文件名 = “/my/directory/filename.txt” 目录 = os.path.dirname(文件名) 我们希望避免覆盖内置函数 dir。此外,filepath 或 fullfilepath 可能是比 filename 更好的语义名称,所以这样写会更好: import os filepath = '/my/directory/filename.txt' directory = os.path.dirname(filepath) 你的最终目标是打开这个文件,你最初声明,写,但你基本上是这样接近这个目标(基于你的代码),它打开文件进行阅读: 如果不是 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) ## 解决方案9: ## > 一个优秀的自由职业者,应该有对需求敏感和精准需求捕获的能力,而huntsbot.com提供了这个机会 我已经把以下内容。不过,这也不是万无一失的。 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 现在正如我所说,这并不是万无一失的,因为我们有可能无法创建目录,并且在此期间有另一个进程创建它。 ## 解决方案10: ## > huntsbot.com全球7大洲远程工作机会,探索不一样的工作方式 检查目录是否存在并在必要时创建它? 对此的直接答案是,假设您不希望其他用户或进程弄乱您的目录的简单情况: if not os.path.exists(d): os.makedirs(d) 或者,如果使目录受制于竞争条件(即,如果在检查路径存在之后,可能已经有其他东西),请执行以下操作: import errno try: os.makedirs(d) except OSError as exception: if exception.errno != errno.EEXIST: raise 但也许更好的方法是通过 tempfile 使用临时目录来回避资源争用问题: import tempfile d = tempfile.mkdtemp() 以下是在线文档中的要点: mkdtemp(suffix=‘’, prefix=‘tmp’, dir=None) 用户可调用函数,用于创建并返回唯一的临时目录。返回值是目录的路径名。该目录只能由创建用户读取、写入和搜索。调用者负责在完成后删除目录。 Python 3.5 中的新功能:pathlib.Path 和 exists\_ok 有一个新的 Path 对象(从 3.4 开始),其中包含许多希望与路径一起使用的方法 - 其中之一是 mkdir。 (对于上下文,我正在使用脚本跟踪我的每周代表。以下是脚本中代码的相关部分,可以让我避免每天针对相同的数据多次访问 Stack Overflow。) 首先是相关的进口: from pathlib import Path import tempfile 我们现在不必处理 os.path.join - 只需用 / 连接路径部分: directory = Path(tempfile.gettempdir()) / 'sodata' 然后我幂等地确保目录存在 - exist\_ok 参数出现在 Python 3.5 中: directory.mkdir(exist_ok=True) 以下是 documentation 的相关部分: 如果exist\_ok 为真,FileExistsError 异常将被忽略(与 POSIX mkdir -p 命令的行为相同),但前提是最后一个路径组件不是现有的非目录文件。 这是脚本的更多内容 - 就我而言,我不受竞争条件的影响,我只有一个进程希望目录(或包含的文件)在那里,并且我没有任何尝试删除的内容目录。 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)) 必须将 Path 对象强制转换为 str,然后其他需要 str 路径的 API 才能使用它们。 也许应该更新 Pandas 以接受抽象基类 os.PathLike 的实例。 ## 解决方案11: ## > huntsbot.com洞察每一个产品背后的需求与收益,从而捕获灵感 在 Python 3.4 中,您还可以使用 brand new pathlib module: 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. `原文链接:https://www.huntsbot.com/qa/Pdg2/how-can-i-safely-create-a-nested-directory?lang=zh_CN` > huntsbot.com提供全网独家一站式外包任务、远程工作、创意产品分享与订阅服务!
相关 Java反射机制:如何安全地访问私有属性 在Java中,反射机制允许我们动态地获取类的信息,包括属性和方法。然而,由于私有属性默认是不可见的,直接通过反射访问可能会抛出异常。 但是,我们可以使用Java的权限管理来安 小灰灰/ 2024年09月11日 07:33/ 0 赞/ 23 阅读
相关 如何安全地使用redis的pop命令 Redis的list经常被当作队列使用,左进右出,一般生产者使用lpush压入数据,消费者调用rpop取出数据。 这是很自然的行为,然而有时会发现lpush成功,但... 水深无声/ 2024年04月18日 10:34/ 0 赞/ 21 阅读
相关 如何安全地创建嵌套目录? 问题描述: 如何检查要写入文件的目录是否存在,如果不存在,则使用 Python 创建目录? > HuntsBot周刊–不定时分享成功产品案例,学习他们如何成功建立自己的 ゞ 浴缸里的玫瑰/ 2024年03月31日 16:51/ 0 赞/ 35 阅读
相关 Python陷阱-如何安全地删除列表元素? 一个常见的任务是在一个列表上迭代,并根据条件删除一些元素。本文将展示如何完成该任务的不同方法,同时展示一些需要避免的陷阱。 假设我们需要修改列表a,并且必须删除所有不是偶数的 ╰半夏微凉°/ 2024年02月05日 23:22/ 0 赞/ 34 阅读
相关 如何让线程安全地停止工作 目录 目标 概念 代码演练 演示stop()方法:强行中断线程(已废弃) 演示interrupt()方法:提醒线程中断 演示isInterrupted()方法:检查 短命女/ 2022年10月08日 05:51/ 0 赞/ 92 阅读
相关 如何安全地嵌入第三方js 转载: [http://www.baiduux.com/blog/2010/07/07/js-safe/][http_www.baiduux.com_blog_2010_07 青旅半醒/ 2022年09月30日 00:45/ 0 赞/ 104 阅读
相关 如何安全地使用辅助驾驶功能? 导语:本文内容来自 360 智能网联汽车安全实验室负责人刘健皓在硬创公开课的分享,由雷锋网旗下栏目“新智驾”整理。 ![如何安全地使用辅助驾驶功能?| 硬创公开课][90] 比眉伴天荒/ 2022年07月13日 06:22/ 0 赞/ 120 阅读
相关 如何正确、安全地停止SpringBoot应用服务 [正确、安全地停止SpringBoot应用服务][SpringBoot] [SpringBoot]: https://www.jianshu.com/ £神魔★判官ぃ/ 2022年03月18日 17:40/ 0 赞/ 164 阅读
相关 linux 创建目录命令_如何使用一个Linux命令创建多个子目录 ![linux 创建目录命令][linux] linux 创建目录命令 ![00\_lead\_image\_creating\_subdirectories\_wih\_ 梦里梦外;/ 2021年07月27日 01:00/ 0 赞/ 807 阅读
还没有评论,来说两句吧...