tempfile.temporary目录contextmanager不使用/tmp fold

2024-06-07 22:14:02 发布

您现在位置:Python中文网/ 问答频道 /正文

我使用tempfile.TemporaryDirectory类作为contextmanager。默认情况下,它应该使用/tmp文件夹。我尝试过使用默认值,也尝试过强制使用/tmp文件夹。它创建调用方脚本所在的临时文件夹。你知道吗

设置:

  • Red Hat 7 Linux版
  • Python 3.6.6版
  • 这个脚本是从詹金斯那里调用的

代码:

import tempfile
import os

print(os.path.dirname(__file__))
TMP_DIR_PREFIX = "my_test_"
with tempfile.TemporaryDirectory(prefix=TMP_DIR_PREFIX, dir="/tmp") as tmp_dir:
       print(tmp_dir)

输出:

>>> python3 /home/my_home/test.py 
home/my_home
home/my_home/my_test_m1vljq2h

我的问题:

  • 有人知道我怎么解决吗?

  • 怎么可能?我已经检查了TemporaryDirectory类的实现,但是我看不出任何原因。如果有人能解释一下原因,我会很高兴的。

我已经阅读了相关的官方文档以及tempfile模块的实现,但是我没有找到任何可能导致这种问题的相关代码部分。你知道吗

注意:如果可能的话,我不想继承和更改本模块的许多元素,但我愿意听取意见。你知道吗

编辑:

完全回溯(来自Jenkins running):

File "/my_path/python/3.6.0/lib/python3.6/threading.py", line 916, in _bootstrap_inner
    self.run()
  File "/my_path/python/3.6.0/lib/python3.6/threading.py", line 864, in run
    self._target(*self._args, **self._kwargs)
  File "/home/my_home/copy_to_location.py", line 143, in upload_files
    with tempfile.TemporaryDirectory(prefix=TMP_DIR_PREFIX, dir="/tmp") as tmp_dir:
  File "/my_path/python/3.6.0/lib/python3.6/tempfile.py", line 790, in __init__
    self.name = mkdtemp(suffix, prefix, dir)
  File "/my_path/python/3.6.0/lib/python3.6/tempfile.py", line 368, in mkdtemp
    _os.mkdir(file, 0o700)
PermissionError: [Errno 13] Permission denied: '/home/my_home/my_test_q1pldmf2'

编辑2:

我无法在本地复制它。这个问题只在詹金斯经常发生!你知道吗

编辑3:

添加的行:

logging.info(tempfile._sanitize_params("my_test_", None, None))

詹金斯产量:

2019-11-08 15:09:26 [Thread-1] [INFO] ('my_test_', '', '/tmp', <class 'str'>)

更改的行:

logging.info(tempfile._sanitize_params("my_test_", None, "/tmp"))

詹金斯补充道:

2019-11-08 15:13:46 [Thread-1] [INFO] ('my_test_', '', '/tmp', <class 'str'>)

Tags: pathinpytestself文件夹homemy
1条回答
网友
1楼 · 发布于 2024-06-07 22:14:02

tempfile.TemporaryDirectory()对象使用^{}从传入的参数创建临时目录。如果您不给它一个dir参数,那么它将使用^{}。你知道吗

如果您正在传递一个dir='/tmp'并且仍然没有看到在/tmp中创建的目录,那么有两种可能性:

  • 你的prefix值不是你想象的那样,而是以/开始的
  • 系统上的tempfile模块已被更改,不再像standard library version distributed with Python 3.6.0那样运行。这些更改可以在磁盘上进行,也可以由其他动态更改行为的Python代码进行。你知道吗

正常行为是mkdtemp()函数调用名为^{}的内部函数,如果设置了dir,则返回gettempdir()的值,否则返回gettempdir()

>>> import tempfile
>>> tempfile._sanitize_params('my_test_', None, '/tmp')
('my_test_', '', '/tmp', <class 'str'>)
>>> tempfile._sanitize_params('my_test_', None, None)
('my_test_', '', '/tmp', <class 'str'>)
>>> tempfile.gettempdir()
'/tmp'

mkdtemp()然后使用该调用的结果(返回更新的prefixsuffixdir以及bytesstr类型)和随机字符串,为您创建一个新目录。你知道吗

这导致了这样一种可能性:您没有正确地排除prefix值确实是您认为的值。mkdtemp()函数使用:

os.path.join(dir, prefix + name + suffix)

dir路径与前缀、候选name(随机值)和后缀(本例中为空字符串)串联起来。但是请注意,^{} function丢弃以/斜杠开头的参数前面的任何path元素:

>>> import os.path
>>> os.path.join("/foo", "bar")
'/foo/bar'
>>> os.path.join("/foo", "/bar")
'/bar'

所以你看到的行为也可以用你的前缀以斜杠开头来解释,所以:

TMP_DIR_PREFIX = "/home/my_home/my_test_"

会立即产生相同的结果:

>>> TMP_DIR_PREFIX = "/home/my_home/my_test_"
>>> tempfile.mkdtemp(prefix=TMP_DIR_PREFIX, dir="/tmp")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/.../lib/python3.6/tempfile.py", line 368, in mkdtemp
    _os.mkdir(file, 0o700)
PermissionError: [Errno 13] Permission denied: '/home/my_home/my_test_v4cqpamm'

这是以前作为issue #35278报告给Python项目的。你知道吗

你可以在Jenkins的工作中包含两个测试来排除这些选项。确保记录TMP_DIR_PREFIX值以及tempfile._sanitize_params(TMP_DIR_PREFIX, None, '/tmp')返回的内容。你知道吗

如果其中一个没有在您的系统上产生预期的输出,那么您就知道您需要集中精力寻找;tempfile模块行为已经改变,或者您认为TMP_DIR_PREFIX具有它所具有的值的假设是不正确的。你知道吗

可以使用以下shell命令检查本地副本是否与发布版本不同:

$ diff -u \
> <(curl -s https://raw.githubusercontent.com/python/cpython/v3.6.0/Lib/tempfile.py) \
> /my_path/python/3.6.0/lib/python3.6/tempfile.py

或者可以计算文件的校验和:

import hashlib
with open(tempfile.__file__, 'rb') as file_to_hash:
    tempfile_checksum = hashlib.sha1(file_to_hash.read()).hexdigest()

并将该校验和值与已发布文件的校验和值进行比较:

$ curl -s https://raw.githubusercontent.com/python/cpython/v3.6.0/Lib/tempfile.py | \
> sha1sum
38ad01ccc5972e193e1b96a1de8b7ba1bd8d289d  -

如果没有任何结果,您可以使用调试器逐步完成调用,或者查看所涉及函数的__module__属性。例如,如果_sanitize_params()被动态改变(monkey patched),那么tempfile._sanitize_params.__module__将不会被设置为'tempfile'。但是,请注意,回溯已经显示TemporaryDirectory.__init__mkdtemp都来自正确的文件,并且可见的两行行号与已发布源中的行号匹配。你知道吗

相关问题 更多 >

    热门问题