Safely create a file if and only if it does not exist with python
我希望根据文件是否已经存在写入文件,仅在文件不存在时写入(在实践中,我希望继续尝试文件,直到找到不存在的文件)。
下面的代码显示了一种可能的攻击者可以插入符号链接的方法,如本文中在文件测试和正在写入的文件之间所建议的。如果代码以足够高的权限运行,则可能覆盖任意文件。
有没有办法解决这个问题?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | import os import errno file_to_be_attacked = 'important_file' with open(file_to_be_attacked, 'w') as f: f.write('Some important content! ') test_file = 'testfile' try: with open(test_file) as f: pass except IOError, e: # symlink created here os.symlink(file_to_be_attacked, test_file) if e.errno != errno.ENOENT: raise else: with open(test_file, 'w') as f: f.write('Hello, kthxbye! ') |
编辑:另请参见Dave Jones的回答:从python 3.3,您可以使用
以下为原始答案
是的,但不使用Python的标准
特别是,您希望使用
Ensure that this call creates the file: if this flag is specified in conjunction with
O_CREAT , and pathname already exists, thenopen() will fail. The behavior ofO_EXCL is undefined ifO_CREAT is not specified.When these two flags are specified, symbolic links are not followed: if pathname is a symbolic link, then
open() fails regardless of where the symbolic link points to.
O_EXCL is only supported on NFS when using NFSv3 or later on kernel 2.6 or later. In environments where NFSO_EXCL support is not provided, programs that rely on it for performing locking tasks will contain a race condition.
所以这并不完美,但是阿法克,这是你最接近避免这种比赛条件。
编辑:其他使用
所有的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | import os import errno flags = os.O_CREAT | os.O_EXCL | os.O_WRONLY try: file_handle = os.open('filename', flags) except OSError as e: if e.errno == errno.EEXIST: # Failed as the file already exists. pass else: # Something unexpected went wrong so reraise the exception. raise else: # No exception, so the file must have been created successfully. with os.fdopen(file_handle, 'w') as file_obj: # Using `os.fdopen` converts the handle to an object that acts like a # regular Python file object, and the `with` context manager means the # file will be automatically closed when we're done with it. file_obj.write("Look, ma, I'm writing to a new file!") |
作为参考,python 3.3在
1 2 | >>> f1 = open('new_binary_file', 'xb') >>> f2 = open('new_text_file', 'x') |
对于python 3.2及以下版本(包括python 2.x),请参考接受的答案。
如果文件不存在,此代码将很容易创建文件。
1 2 3 | import os if not os.path.exists('file'): open('file', 'w').close() |