在 Python 中更改文件权限

Posted

技术标签:

【中文标题】在 Python 中更改文件权限【英文标题】:Changing file permission in Python 【发布时间】:2013-04-21 09:29:12 【问题描述】:

我正在尝试更改文件访问权限:

os.chmod(path, mode)

我想让它只读:

os.chmod(path, 0444)

有没有其他方法使文件只读?

【问题讨论】:

我见过一些像 S_IRUSR..这是怎么工作的??? 我认为它只是设置了一点,所以当你或他们在一起时,你会得到 0444 如果你的意思是问“我如何使用符号权限名称,它们是什么意思”,你的表达有严重缺陷。 @AbulHasnat。你有什么解决办法吗? 【参考方案1】:

os.chmod(path, 0444) 在 Python 2.x 中用于更改文件权限的 Python 命令。对于 Python 2 和 Python 3 组合解决方案,请将 0444 更改为 0o444

您始终可以使用 Python 通过 subprocess 调用 chmod 命令。我认为这仅适用于 Linux。

import subprocess

subprocess.call(['chmod', '0444', 'path'])

【讨论】:

os.chmod 可能是正确的函数,但 0444(在 os.chmod(path, 0444) 中)作为 int 会导致 SyntaxError(由于前导 0),并且在字符串形式中它不会给出想要的效果。您必须将数字转换为方法使用的数字系统,这是不一样的。也许你知道,但其他人可能不知道。 别在意我的评论!对不起因巴尔罗斯。你没事。显然,0444 在 Python 2.x 中效果很好。但是,它会在 Python 3.x 中导致 SyntaxError。要修复它,只需在 Python 3.x 中执行 0o444 即可。 这不适用于另一台服务器上的文件。你能建议这种情况吗?谢谢 产生八进制数的与版本无关的方法是: int("444", 8) 但是请注意,建议使用 stat 模块中定义的符号值的另一个答案可能是清洁工。【参考方案2】:
os.chmod(path, stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH)

stat

以下标志也可用于 os.chmod():

stat.S_ISUID 设置 UID 位。

stat.S_ISGID 设置组 ID 位。这个位有几个特殊用途。为了 一个目录,它指示 BSD 语义将用于该目录 目录:在那里创建的文件从 目录,而不是来自创建进程的有效组 ID, 并且在那里创建的目录也将设置 S_ISGID 位。为一个 未设置组执行位 (S_IXGRP) 的文件,则 set-group-ID 位指示强制文件/记录锁定(另请参阅 S_ENFMT)。

stat.S_ISVTX 粘性位。当在目录上设置此位时,这意味着 该目录中的文件只能由 文件的所有者、目录的所有者或特权 过程。

stat.S_IRWXU 文件所有者权限的掩码。

stat.S_IRUSR 所有者拥有读取权限。

stat.S_IWUSR Owner 有写权限。

stat.S_IXUSR Owner 有执行权限。

stat.S_IRWXG 组权限掩码。

stat.S_IRGRP组有读权限。

stat.S_IWGRP组有写权限。

stat.S_IXGRP组有执行权限。

stat.S_IRWXO 其他人(不在组中)的权限掩码。

stat.S_IROTH其他人有读权限。

stat.S_IWOTH其他人有写权限。

stat.S_IXOTH其他人有执行权限。

stat.S_ENFMT System V 文件锁定实施。此标志是共享的 使用 S_ISGID:文件/记录锁定对不执行的文件强制执行 设置组执行位 (S_IXGRP)。

stat.S_IREAD S_IRUSR 的 Unix V7 同义词。

stat.S_IWRITE S_IWUSR 的 Unix V7 同义词。

stat.S_IEXECS_IXUSR 的 Unix V7 同义词。

【讨论】:

stat 中的常量只是方便人类可读的糖。 S_IRUSR 是 0400,S_IRGRP 是 040,S_IROTH 是 4;将它们与按位 OR 组合产生 0444。您可以改为添加它们,但在一般情况下,OR 是正确的,因为即使存在重叠位(0444 OR 0444 是 0444,它也会起作用,而加法会产生不同的错误值)。 使用+ 似乎也可以代替|。我不知道是否有理由在另一个之上使用一个。 对此没有任何解释,除非您已经知道 stat 的作用,否则您必须阅读 cmets、cmets 或链接才能理解它。稍微解释一下就会好很多。 @Shule | 在组合来自两个位掩码的位时更合适。但是,如果每个掩码只有一个单独的位集,就像上面答案中的所有常量一样,那么+ 是等效的。 你必须小心机智+ 操作预先存在的模式时。如果已设置模式,则 + 将不起作用,但 | 将起作用。例如,mode = stat.S_IWUSR + stat.S_IRUSR; ... some code ...; mode = mode + stat.S_IWUSR; 不起作用,但最后一个命令将适用于 |【参考方案3】:

所有当前的答案都破坏了 non-writing 权限:它们使文件对每个人都可读但不可执行。当然,这是因为最初的问题要求444 权限——但我们可以做得更好!

这里有一个解决方案,它使所有单独的“读取”和“执行”位保持不变。我编写了冗长的代码以使其易于理解;如果你愿意,你可以让它更简洁。

import os
import stat

def remove_write_permissions(path):
    """Remove write permissions from this path, while keeping all other permissions intact.

    Params:
        path:  The path whose permissions to alter.
    """
    NO_USER_WRITING = ~stat.S_IWUSR
    NO_GROUP_WRITING = ~stat.S_IWGRP
    NO_OTHER_WRITING = ~stat.S_IWOTH
    NO_WRITING = NO_USER_WRITING & NO_GROUP_WRITING & NO_OTHER_WRITING

    current_permissions = stat.S_IMODE(os.lstat(path).st_mode)
    os.chmod(path, current_permissions & NO_WRITING)

为什么会这样?

作为John La Rooy pointed out,stat.S_IWUSR 基本上意味着“用户写权限的位掩码”。我们希望将相应的权限位设置为 0。为此,我们需要 exact contrast 位掩码(即,在该位置具有 0 的位掩码,而在其他位置具有 1 的位掩码)。翻转所有位的~ 运算符正是为我们提供了这一点。如果我们通过“按位与”运算符 (&) 将其应用于任何变量,它会将相应的位清零。

我们也需要用“组”和“其他”权限位重复这个逻辑。在这里,我们可以通过将它们全部组合在一起(形成NO_WRITING 位常量)来节省一些时间。

最后一步是get the current file's permissions,实际执行按位与运算。

【讨论】:

似乎必须有一种更简洁的方式来做到这一点。【参考方案4】:

无需记住标志。请记住,您总是可以这样做:

subprocess.call(["chmod", "a-w", "file/path])

不便携但易于编写和记忆:

u - 用户 g - 组 o - 其他 一个 - 全部 + 或 -(添加或删除权限) r - 读取 w - 写 x - 执行

请参阅man chmod 了解更多选项和更详细的说明。

【讨论】:

这种方法的关键问题是它假定它是在一个类Unix系统上。这不是可移植的,因为它不能在 Windows 上运行。您应该按照 Gitano 的回答中的建议使用 os.chmod【参考方案5】:

只需在八进制中包含权限整数(适用于 python 2 和 python3):

os.chmod(path, 0o444)

【讨论】:

【参考方案6】:

仅供参考,这里是一个函数,用于将具有 9 个字符的权限字符串(例如 'rwsr-x-wt')转换为可与 os.chmod() 一起使用的掩码。

def perm2mask(p):
        
    assert len(p) == 9, 'Bad permission length'
    assert all(p[k] in 'rw-' for k in [0,1,3,4,6,7]), 'Bad permission format (read-write)'
    assert all(p[k] in 'xs-' for k in [2,5]), 'Bad permission format (execute)'
    assert p[8] in 'xt-', 'Bad permission format (execute other)'
    
    m = 0
    
    if p[0] == 'r': m |= stat.S_IRUSR 
    if p[1] == 'w': m |= stat.S_IWUSR 
    if p[2] == 'x': m |= stat.S_IXUSR 
    if p[2] == 's': m |= stat.S_IXUSR | stat.S_ISUID 
    
    if p[3] == 'r': m |= stat.S_IRGRP 
    if p[4] == 'w': m |= stat.S_IWGRP 
    if p[5] == 'x': m |= stat.S_IXGRP 
    if p[5] == 's': m |= stat.S_IXGRP | stat.S_ISGID 
    
    if p[6] == 'r': m |= stat.S_IROTH 
    if p[7] == 'w': m |= stat.S_IWOTH 
    if p[8] == 'x': m |= stat.S_IXOTH 
    if p[8] == 't': m |= stat.S_IXOTH | stat.S_ISVTX
    
    return m

请注意,设置 SUID/SGID/SVTX 位将自动设置相应的执行位。否则,生成的权限将无效(ST 个字符)。

【讨论】:

【参考方案7】:

在权限号前加0即可: 例如 - 我们要授予所有权限 - 777 语法:os.chmod("file_name" , permission)

import os
os.chmod("file_name" , 0777)

Python 3.7 版不支持这种语法。八进制文字需要 '0o' 前缀 - 这是我在 PyCharm 中得到的评论

所以对于python 3.7,它将是

import os
os.chmod("file_name" , 0o777)

【讨论】:

【参考方案8】:

可以用,pathlib也可以

from pathlib import Path

fl = Path("file_name")

fl.chmod(0o444)

【讨论】:

【参考方案9】:

在 Python 3.4+ 中,当使用 pathlib.Path 对象时,您可以直接调用 chmod() 作为路径对象上的方法。下面的例子在the docs中给出:

>>> p = Path('setup.py')
>>> p.stat().st_mode
33277
>>> p.chmod(0o444)
>>> p.stat().st_mode
33060

【讨论】:

以上是关于在 Python 中更改文件权限的主要内容,如果未能解决你的问题,请参考以下文章

在Linux系统中,如何更改文件的访问权限

无法在linux中更改文件权限

WIN10需要来自管理员权限才能对此文件进行更改

如何在 Ubuntu 中更改文件权限 [重复]

你需要来自 计算机管理员 的权限才能对此文件进行更改

如何更改文件权限