【问题标题】:Check if file is readable with Python: try or if/else?检查文件是否可以用 Python 读取:try 还是 if/else?
【发布时间】:2015-08-18 13:13:31
【问题描述】:

我有以下代码:

import glob, os
for file in glob.glob("\\*.txt"):
    if os.access(file, os.R_OK):
        # Do something
    else:
        if not os.access(file, os.R_OK):
            print(file, "is not readable")
        else:
            print("Something went wrong with file/dir", file)
        break

但我不完全确定这是否是正确的做法。错误使用trycatch 会更好吗?如果是这样,我该如何尝试以提高可读性?请注意我的 else 语句中的 break。一旦无法读取文件,我就想中止循环。

【问题讨论】:

  • 您可以尝试打开文件以读取并捕获产生的异常(如果有)。这也将比您当前的方法更强大,因为在两次调用 os.access() 之间文件可能变得不可读(甚至消失)。
  • 您实际上是在阅读# Do something 部分中的文件还是只是想测试它的可读性?
  • @PM2Ring 我实际上正在那里读取文件。

标签: python if-statement try-catch


【解决方案1】:

一种更明确的方法来检查file 是否实际上是一个文件而不是目录,例如,它是可读的:

from os import access, R_OK
from os.path import isfile

file = "/some/path/to/file"

assert isfile(file) and access(file, R_OK), \
       f"File {file} doesn't exist or isn't readable"

【讨论】:

  • 我更喜欢这种方法,即使它为文件在您打开之前消失或更改留出了空间。
  • 请注意,如果 Python 通过传递 -O 选项以优化模式执行,则不会执行断言行 (docs.python.org/3/reference/simple_stmts.html#assert)
  • assert 的好点子,这只是一个演示,您可以更改为 if 声明。
【解决方案2】:

在 Python 文化中,ask forgiveness, not permission 更常见,因此最好捕获异常:

for filename in glob.glob('*.txt'):
    try:
        with open(filename) as fp:
            # work with the file

    except IOError as err:
        print "Error reading the file {0}: {1}".format(filename, err)
        break

这样您还可以避免任何双重检查或竞争条件。

【讨论】:

  • ask forgiveness, not permission 链接已损坏。
  • @Gautam 替换为同一作者 2012 年的同一演讲。
【解决方案3】:

对我来说,在与使用 if-else 相同的范围内使用 try-except 不会获得可读性。异常的价值在于它们可以在调用树的更高级别被捕获。

只移出一层,我们避免使用break 声明:

import glob, os
try:
    for file in glob.glob("\\*.txt"):
        with open(file) as fp:
            # do something with file
except IOError:
    print("could not read", file)

但异常的真正天才在于代码消失了:

# Operate on several files
# SUCCESS: Returns None
# FAIL: Raises exception
def do_some_files():
    for file in glob.glob("\\*.txt"):
        with open(file) as fp:
            # do something with file

现在调用程序有责任在失败时显示有用的错误消息。我们已经将处理失败的责任完全从这段代码中移到了另一个领域。

事实上,我们可以将责任完全从我们的程序中转移到解释器中。在这种情况下,解释器将打印一些有用的错误消息并终止我们的程序。如果 Python 的默认消息对您的用户来说足够好,我建议不要检查错误根本。因此,您的原始脚本变为:

import glob, os
for file in glob.glob("\\*.txt"):
    # Do something

【讨论】:

  • 你的功夫更好,不得不承认。
  • 作为对您最后一个建议的回答,解释器是否会跳过不可读的文件而不是停止循环并停止?因为我们从不定义发生错误时需要做什么
  • 不,@BramVanroy,最终的短脚本不会跳过不可读的文件。 #Do Something 中假定的 open() 在尝试打开无法读取的文件时会引发异常。这个异常会被解释器捕捉到,它会打印一条错误信息并退出。也就是说,并非巧合,正是您问题中的程序所做的:打印错误消息并退出。我的短版和长版的行为之间的唯一区别是错误消息的文本。
  • 我认为,考虑到每个文件的代码循环文件,会引发错误,但不会停止循环。很高兴知道它的情况。谢谢。
  • IOError: [Errno 2] No such file or directory: 'XXXAF1D4.TMP' 这样的错误呢?这是来自被调用的 20 个不同函数之一的临时文件。没有上下文,你怎么知道失败的原因?
【解决方案4】:
try:
        # check to see if file is readable
        with open(filename) as tempFile:





except Exception as e:
        print e
        # here you can modify the error message to your liking

这通常是我所做的。 它健壮且直接

【讨论】:

  • 糟糕,现在应该解决这个问题
  • 永远不要在没有直接“raise”的情况下使用“except Exception”!
猜你喜欢
  • 1970-01-01
  • 2013-06-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多