Python中如何使用os.umask()函数

21
我正在尝试使用os模块设置umask。请注意,我在我的~/.profile中设置的普通umask是umask 0027。
在bash shell中,
umask 0022

将允许创建具有权限的文件

-rw-r--r--

然而,当我们导入os模块并执行以下操作:

os.umask(0022)
[do some other code here that creates a file]

我获取权限的方式是

----------

首先,我该如何让os.umask(mask)的行为像shell中的umask一样?

其次,这两者之间的差异逻辑是什么?

注意:我尝试将0022转换为十进制,以防它期望一个十进制数,具体方法如下:

os.umask(18)

但它给出了权限

-----w--w-

还要注意的是,我试过了

os.umask(00022)

并且

os.mask(0o0022)

这也没有起作用。


文件已经存在了吗?在这种情况下,您需要使用chmod。 - John La Rooy
@Ignacio Vazquez-Abrams:先尝试在shell中设置umask 0027,然后再运行脚本或调用解释器。 - narnie
@Ignacio Vazquez-Abrams:你说得对,我也无法通过一个简单的Python测试程序来分离我的代码。很奇怪,因为我正在使用相同的技术。 - narnie
1
使用 old_mask = os.umask(0o000) 然后 os.makedirs(./foo/bar) 创建目录时,会按预期设置为 777。而 oct(old_mask) 给出的是 022,这是正确的(Unix 上的默认 umask)。 - Stan
相关链接: https://dev59.com/O2Uo5IYBdhLWcg3w_DpK - Ciro Santilli OurBigBook.com
显示剩余4条评论
4个回答

31

我认为是对umask的误解。 umask设置的是默认拒绝权限,而不是默认允许权限。 因此

import os
oldmask = os.umask (0o022)
fh1 = os.open ("qq1.junk", os.O_CREAT, 0o777)
fh2 = os.open ("qq2.junk", os.O_CREAT, 0o022)
os.umask (oldmask)
os.close (fh1)
os.close (fh2)

确实应该生成以下文件:

-rwxr-xr-x 1 pax pax 0 Apr 24 11:11 qq1.junk
---------- 1 pax pax 0 Apr 24 11:11 qq2.junk

umask 022会移除组和其他用户的写权限,这正是我们在那里看到的行为。我发现回到八进制数代表的二进制有助于理解:

 usr grp others 
-rwx rwx rwx is represented in octal as 0777, requested for qq1.junk
-000 010 010 umask of 022 removes any permission where there is a 1
-rwx r-x r-x is the result achieved requesting 0777 with umask of 022

---- -w- -w- is represented in octal as 0022, requested for qq2.junk
-000 010 010 umask of 022 removes any permission where there is a 1
---- --- --- is the result achieved requesting 0022 with umask of 022

程序按照您要求的方式运行,但不一定是您认为它应该的方式。这是计算机中常见的情况 :-)


1
umask 022应该会为目录设置755权限,但不适用于文件。对于文件,它应该是644。换句话说,使用umask 022,目录应该是rwxr-xr-x,而文件应该是rw-r--r-- - Dominik

10

在谨慎挑选和兼容Python 3k的情况下,这是我的略有不同的答案(仍然没有解释OP的原始问题):

old_umask = os.umask(0o022) # u=rwx,g=rx,o=rx
try:
    # do stuff

finally:
    os.umask(old_umask)

不兼容2.x版本;2.x umask是一个直接的系统调用,需要整数并在八进制上抛出TypeError异常。 - fatal_error
@CraigYounkins 你说得对!我不确定我从哪里得到的。 :) - fatal_error

8

您可能需要向我们展示构成以下代码的代码:

[do some other code here that creates a file]

您的代码在我的系统上运行正常:

import os
oldmask = os.umask (022)
fh1 = os.open ("qq1.junk", os.O_CREAT, 0777)
fh2 = os.open ("qq2.junk", os.O_CREAT, 0022)
os.umask (oldmask)
os.close (fh1)
os.close (fh2)

生成以下文件:
-rwxr-xr-x 1 pax pax 0 Apr 24 11:11 qq1.junk
---------- 1 pax pax 0 Apr 24 11:11 qq2.junk

您还需要注意恢复旧的umask值,这可以将其对本地操作的影响最小化。
从上面的结果中可以看出,您还需要知道umask值是从您用于创建文件的模式中“减去”的,而我们不知道在您的特定情况下该模式是什么。
即使在您的bash示例中也很明显,因为使用777模式创建一个umask值为022的文件将导致r-xr-xr-x,而不是您所拥有的rw-r--r--
根据您在下面的评论中指出您正在使用open而不是os.open,Python源代码的粗略扫描似乎表明这将转换为使用0666作为初始模式的C fopen调用。这得到了稍微修改的代码的支持:
import os
oldmask = os.umask (022)
fh3 = open ("qq3.junk", "w")
os.umask (0)
fh4 = open ("qq4.junk", "w")
os.umask (oldmask)
fh3.close()
fh4.close()

这让我们得到了:
-rw-r--r-- 1 pax pax 0 Apr 24 11:44 qq3.junk
-rw-rw-rw- 1 pax pax 0 Apr 24 11:44 qq4.junk

所以我不确定为什么你的情况下会得到 0000 权限。

运行上述程序并查看在您的环境中的结果可能会有所帮助。如果结果与我的相同,则问题可能出在其他地方。


我在bash shell中执行了umask 0022,然后执行了touch /tmp/test,接着执行了ls -l /tmp/test,他们复制并粘贴了权限。我认为你混淆了创建文件(其中假定不需要执行)和创建目录(其中假定需要执行权限)之间的差异。 - narnie
@narnie,这完全取决于创建文件的代码。显然,touch在使用模式方面与ld有不同的规则。我想说的是,文件的权限取决于umask值和模式,缺失的代码是告诉我们模式的那一部分。 - paxdiablo
我使用的生成文件的代码相当复杂,因为我在传递文件处理程序。无论.profile umask设置为什么(我的设置为0027),我都希望umask为0022。要点是我只是做f = open(filename,'w'),然后将文件对象传递给控制整个对象的类,该类具有使用f对象编写对象的写入方法,返回,其中运行f.close()。 - narnie
@paxdiable,我认为你已经找到了问题所在。大多数用户的umask默认为0022。我希望我的代码能够处理不同的umask场景。我希望我的umask设置只能被我和我的主要组读取,而不能被任何其他系统用户读取。但是,也可能是open(filename,'w')不关心系统umask是什么。我不确定python如何处理这个问题。 - narnie
1
@narnie,我认为在较低的级别上,Python只是调用fopen来执行此操作,应该使用0666模式(在umask减法之前)。这并不能解释为什么您得到了0000。也许使用os.open(而不是open)以特定的0777模式和任何您想要的umask会更容易些。 - paxdiablo
显示剩余2条评论

0

尽管这似乎是一个直接的系统调用,但在这种情况下,您使用的Python版本似乎很重要:

看起来os.open在Python 2.x和Python 3.x中处理预先存在的umask方式不同,可能是因为2.x更接近操作系统,而3.x进行了更多的抽象。

https://docs.python.org/2/library/os.html “默认模式为0777(八进制),并且当前的umask值首先被屏蔽掉。

https://docs.python.org/3/library/os.html中没有类似的声明。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接