在python中检查文件的权限


问题内容

我正在尝试检查给定指定路径的文件的可读性。这是我所拥有的:

def read_permissions(filepath):
    '''Checks the read permissions of the specified file'''
    try:
        os.access(filepath, os.R_OK) # Find the permissions using os.access
    except IOError:
        return False

    return True

这可以正常运行,并且在运行时返回True或False作为输出。但是,我希望错误消息来自errno它。这是我认为我必须做的(但是我知道这里有问题):

def read_permissions(filepath):
    '''Checks the read permissions of the specified file'''
    try:
        os.access(filepath, os.R_OK) # Find the permissions using os.access
    except IOError as e:
        print(os.strerror(e)) # Print the error message from errno as a string

    print("File exists.")

但是,如果我键入一个不存在的文件,它会告诉我该文件存在。有人可以帮我做错什么(以及将来可以做些什么来避免这个问题)?我还没有看到有人尝试使用os.access。我也开放其他选项来测试文件的权限。发生问题时,有人可以帮助我如何发出适当的错误消息吗?

另外,这可能也适用于我的其他功能(os.access在检查其他内容时,它们仍会使用,例如使用存在文件os.F_OK和使用写入文件的权限os.W_OK)。这是我尝试模拟的一种示例:

>>> read_permissions("located-in-restricted-directory.txt") # Because of a permission error (perhaps due to the directory)
[errno 13] Permission Denied
>>> read_permissions("does-not-exist.txt") # File does not exist
[errno 2] No such file or directory

通过将适当的错误消息返回给问题,我正在尝试模拟这种事情。我希望这将有助于避免对我的问题感到困惑。

我可能应该指出,虽然我已经阅读了os.access文档,但以后不会尝试打开该文件。我只是试图创建一个模块,其中的某些组件将用来检查特定文件的权限。我有一个基线(我提到的第一段代码),可以作为我其余代码的决策者。在这里,我只是在尝试再次编写它,但是以一种用户友好的方式(不只是True或just
False,而是带有完整的消息)。由于IOError可以通过几种不同的方式(例如,权限被拒绝或目录不存在)提出,因此,我试图使我的模块识别并发布问题。我希望这可以帮助您确定任何可能的解决方案。


问题答案:

os.access``False当文件不存在时,无论传递的mode参数如何,都会返回。

这在文档中os.access没有明确说明,但这并不是非常令人震惊的行为。毕竟,如果文件不存在,则可能无法访问它。检查docs所建议的access(2)手册页提供了另一个线索,因为access返回-1的条件多种多样。无论如何,您都可以像我一样简单地检查IDLE中的返回值:

>>> import os
>>> os.access('does_not_exist.txt', os.R_OK)
False

在Python中,通常不建议在尝试实际做有用的事情之前先检查类型等。这种哲学通常用首字母缩写EAFP来表达,缩写是EAFP,
比Permission更容易寻求宽恕 。如果再次参考文档,您会发现在当前情况下这特别相关:

注:
使用access()检查,如果用户被授权例如竟这样做使用前打开一个文件open()创建一个安全漏洞,因为用户可能会利用检查和打开操作它的文件之间的时间间隔短。最好使用
EAFP技术。例如:

if os.access("myfile", os.R_OK):
    with open("myfile") as fp:
        return fp.read()
return "some default data"

最好写成:

try:
    fp = open("myfile")
except IOError as e:
    if e.errno == errno.EACCES:
        return "some default data"
    # Not a permission error.
    raise
else:
    with fp:
        return fp.read()

如果您有其他原因需要检查权限,而不是在致电之前先猜测用户open(),则可以查看如何使用Python检查文件是否存在?对于一些建议。请记住,如果您确实需要引发异常,则可以随时进行raise处理。无需野外狩猎。


由于IOError可以通过几种不同的方式来提出(例如,权限被拒绝或目录不存在),所以我试图使我的模块识别并发布问题。

这就是上面第二种方法所做的。看到:

>>> try:
...     open('file_no_existy.gif')
... except IOError as e:
...     pass
...
>>> e.args
(2, 'No such file or directory')
>>> try:
...     open('unreadable.txt')
... except IOError as e:
...     pass
...
>>> e.args
(13, 'Permission denied')
>>> e.args == (e.errno, e.strerror)
True

但是您需要选择一种方法或另一种方法。如果您请求宽恕, 在try-except块中 执行此操作
(打开文件),并适当地处理后果。如果成功,那么您就知道成功了,因为没有例外。

在另一方面,如果你问权限(又名LBYL, 三思而后 在这一点,和其他方式),你 仍然 不知道你是否能成功地打开该文件,直到你真正 去做
它。如果在检查其权限后文件被移动怎么办?如果您没有想到要解决的问题怎么办?

如果您仍然想征求许可,请不要使用try-except;您没有 做任何事情, 所以您不会抛出错误。而是使用带有条件调用的条件语句os.access