python 在临时文件夹中克隆git仓库时出现权限错误

cgyqldqp  于 2023-01-08  发布在  Python
关注(0)|答案(2)|浏览(195)

我认为,问题代码可以解释的内容比我在文本中所能说的要多。我已经对它进行了大量的简化,以保持它的可读性,但本质上这就是我正在运行的。

def main():
    with tempfile.TemporaryDirectory() as td:
        for repo in repos:
            subprocess.run("git clone --mirror {} {}".format(os.path.join(td, repo.path), repo.url)

克隆部分工作正常,成功地遍历了整个列表,但当“with ... as ...”退出时,它会抛出以下错误(回溯从上下文管理器的__exit__开始):

os.unlink(fullname)
PermissionError: [WinError 5] Access is denied: 'C:\\Users\\USERNAME\\AppData\\Local\\Temp\\tmp4ew2qffb\\sources\\REPONAME\\objects\\pack\\pack-abd0ff87083dbbcb90f707d8f2d53c730583bb6e.idx'

以管理员身份运行脚本也没有帮助。这里出了什么问题?
编辑:我已经深入研究过了,结果发现python 3.7的临时目录清理不支持清理Windows上的只读文件。

y1aodyip

y1aodyip1#

通常在with tempfile...使用结束时添加,因此在离开上下文之前,类似于

for fname in pathlib.Path(td).glob('**/*.*'):  # make all writable for deletion
    fname.chmod(stat.S_IWRITE)

应该会有帮助。
注意,偶尔我仍然会看到PermissionError(“仍在使用中”),但不确定这在我的环境中是否有什么特殊之处。

wd2eg0qa

wd2eg0qa2#

这与Python中的删除只读目录相关但不完全相同-this answer中的一个可能的解决方案是在退出TemporaryDirectory()上下文管理器之前显式地修复权限。有关详细信息,请参见akaihola/darker#453。以下是实现的副本:

import os
import sys
from pathlib import Path
from typing import Union

WINDOWS = sys.platform.startswith("win")

def fix_py37_win_tempdir_permissions(dirpath: Union[str, Path]) -> None:
    """Work around a `tempfile` clean-up issue on Windows with Python 3.7

    Call this before exiting a ``with TemporaryDirectory():`` block or in teardown for
    a Pytest fixture which creates a temporary directory.

    See discussion in https://github.com/akaihola/darker/pull/393
    Solution borrowed from https://github.com/python/cpython/pull/10320

    :param dirpath: The root path of the temporary directory

    """
    if not WINDOWS or sys.version_info >= (3, 8):
        return
    for root, dirs, files in os.walk(dirpath):
        for name in dirs + files:
            path = os.path.join(root, name)
            try:
                os.chflags(path, 0)  # type: ignore[attr-defined]
            except AttributeError:
                pass
            os.chmod(path, 0o700)

下面是如何在Pytest单元测试中使用它,或者在使用tempfile创建临时目录时使用它:

import pytest

from my_utils import fix_py37_win_tempdir_permissions

@pytest.fixture
def myfixture(tmp_path):
    # setup code here
    yield tmp_path
    fix_py37_win_tempdir_permissions(tmp_path)

def myfunc():
    with TemporaryDirectory() as tmpdir:
        # work on the temporary directory here
        fix_py37_win_tempdir_permissions(tmp_path)

相关问题