Почему файл моего обработчика файла во временном каталоге не может быть очищен на Windows? - PullRequest
3 голосов
/ 21 января 2020

У меня есть код, который отлично работает на unix системах, но не на Windows. Я хотел бы сделать это кроссплатформенным, но я бьюсь головой о стену. Минимальное повторение выглядит следующим образом:

Файл 1: foo.py

import os
import sys
import logging

logging.basicConfig(level=logging.INFO, stream=sys.stdout)
logger = logging.getLogger('foo')

def main(dir):
    logger.addHandler(logging.FileHandler(
        os.path.join(dir, 'temporary.log')
    ))

    logger.info("Hello, world!")

Файл 2: main.py

from foo import main

import tempfile

if __name__ == "__main__":
    with tempfile.TemporaryDirectory("test") as tmp:
        main(tmp)

Что я ожидал бы, так это временный каталог будет создан, файл будет создан в том, куда будут отправляться журналы, и затем оба будут очищены, когда tmp выйдет из области видимости.

Вместо этого Windows выдает ошибку:

PermissionError: [WinError 32] The process cannot access the file because it is being used by another process: '...'

Я пытался изменить режим FileHandler с режима добавления, я пытался вручную очистить файлы и каталоги, я пытался отложить создание файла до его регистрации и запуска уровня журнала, и я даже пытался создать экземпляр регистратора внутри foo.main в надежде, что никаких ссылок на обработчик не будет сохранено - независимо от того, я все еще вижу эту ошибку.

Как я могу это исправить?

1 Ответ

2 голосов
/ 21 января 2020

Вам нужно закрыть обработчик, который закрывает файл. Тогда удаление временного каталога должно сработать. Я сделал следующие изменения:

# foo.py
import os
import sys
import logging

logging.basicConfig(level=logging.INFO, stream=sys.stdout)
logger = logging.getLogger('foo')

def main(dir):
    h = logging.FileHandler(os.path.join(dir, 'temporary.log'))
    logger.addHandler(h)
    logger.info("Hello, world!")
    logger.removeHandler(h)
    return h

и

# main.py
from foo import main

import tempfile

if __name__ == "__main__":
    with tempfile.TemporaryDirectory("test") as tmp:
        print('Using temp dir %s' % tmp)
        h = main(tmp)
        h.close()

После чего, похоже, сработает:

~> python3 c:\temp\main.py
Using temp dir C:\Users\Vinay\AppData\Local\Temp\tmp60qirkhutest
INFO:foo:Hello, world!

~> dir AppData\Local\Temp\tmp60qirkhutest
 Volume in drive C has no label.
 Volume Serial Number is D195-0C0D

 Directory of C:\Users\Vinay\AppData\Local\Temp

File Not Found

Если вы закомментируете h.close() линия, она терпит неудачу как прежде.

...