Объект tempfile.TemporaryDirectory()
использует tempfile.mkdtemp()
для создания временного каталога из переданных аргументов. Это, в свою очередь, будет использовать tempfile.gettempdir()
, если вы этого не сделаетепередайте ему аргумент dir
.
Если вы передаете dir='/tmp'
и все еще не видите каталог, созданный в /tmp
, то есть две возможности:
- ваше
prefix
значение не то, что вы думаете, а скорее начинается с /
tempfile
модуля в вашей системе имеетбыл изменен и больше не работает так же, как стандартная версия библиотеки , распространяемая с Python 3.6.0 . Изменения могли быть сделаны на диске или с помощью другого кода Python, который динамически изменял поведение.
Обычное поведение для функции mkdtemp()
- вызывать внутреннюю функцию с именем * 1032. *, который возвращает dir
без изменений, если он установлен, и значение 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()
затем использует результаты этого вызова (возвращая обновленный prefix
, suffix
, dir
и тип bytes
или str
) вместе со случайными строками, чтобы создать для вас новый каталог.
Это приводит к тому, что у вас нетПравильно исключил, что значение prefix
действительно то, что вы думаете. Функция mkdtemp()
использует:
os.path.join(dir, prefix + name + suffix)
, чтобы соединить путь dir
с конкатенацией вашего префикса, кандидата name
(случайное значение) и суффикса (пустая строка в вашем случае). Но обратите внимание, что os.path.join()
функция будет отбрасывать любые элементы пути, которые предшествуют аргументу, начинающемуся с /
косой черты :
>>> 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'
Об этом ранее сообщалось проекту Pythonas issue # 35278 .
Вы можете тривиально включить в свою работу Jenkins два теста, чтобы исключить эти параметры. Убедитесь, что вы записали значение TMP_DIR_PREFIX
, а также то, что возвращает tempfile._sanitize_params(TMP_DIR_PREFIX, None, '/tmp')
.
Если какой-либо из них не дает ожидаемого результата в вашей системе, то вы знаете, что вам нужно сосредоточиться на поиске;либо изменилось поведение модуля tempfile
, либо вы предполагаете, что значение TMP_DIR_PREFIX
имеет неверное значение.
Вы можете проверить, отличается ли локальная копия от версии для публикации, с помощью следующей команды оболочки:
$ 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()
был динамически изменен ( обезьяна исправлена ), тогда tempfile._sanitize_params.__module__
не будет установлен на 'tempfile'
, например. Тем не менее, обратите внимание, что ваша трассировка уже показывает, что TemporaryDirectory.__init__
и mkdtemp
взяты из правильного файла и что номера строк для двух видимых строк совпадают с номерами в опубликованном источнике.