Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/277.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 在重复的os.path.isdir调用中出现巨大内存泄漏?_Python_Memory Leaks_Python 2.7_System Calls - Fatal编程技术网

Python 在重复的os.path.isdir调用中出现巨大内存泄漏?

Python 在重复的os.path.isdir调用中出现巨大内存泄漏?,python,memory-leaks,python-2.7,system-calls,Python,Memory Leaks,Python 2.7,System Calls,我编写了一些与扫描目录有关的脚本,在调用os.path.isdir时注意到严重的内存泄漏,因此我尝试了以下代码片段: def func(): if not os.path.isdir('D:\Downloads'): return False while True: func() 几秒钟之内,Python进程就达到了100MB的RAM 我在想到底发生了什么。似乎只有当路径确实是有效的目录路径时(意味着不执行“return False”),巨大的内存泄漏才会生效。

我编写了一些与扫描目录有关的脚本,在调用os.path.isdir时注意到严重的内存泄漏,因此我尝试了以下代码片段:

def func():
    if not os.path.isdir('D:\Downloads'):
        return False
while True:
    func()
几秒钟之内,Python进程就达到了100MB的RAM

我在想到底发生了什么。似乎只有当路径确实是有效的目录路径时(意味着不执行“return False”),巨大的内存泄漏才会生效。 另外,查看相关调用(如os.path.isfile)中发生的情况也很有趣

想法

编辑: 我想我发现了什么。 虽然isfile和isdir是在genericpath模块中实现的,但在Windows系统上,isdir是从内置nt导入的。 所以我不得不下载2.7.3的源代码(我早就该下载了…)

经过一点搜索,我在\Modules\posixmodule.c中找到了posix_uuuisdir函数,我假设它是从nt导入的“isdir”函数

这部分功能(和注释)吸引了我的眼球:

if (PyArg_ParseTuple(args, "U|:_isdir", &po)) {
        Py_UNICODE *wpath = PyUnicode_AS_UNICODE(po);

        attributes = GetFileAttributesW(wpath);
        if (attributes == INVALID_FILE_ATTRIBUTES)
            Py_RETURN_FALSE;
        goto check;
    }
    /* Drop the argument parsing error as narrow strings
       are also valid. */
    PyErr_Clear();
似乎这一切都归结为Unicode/ASCII处理错误


我刚刚用unicode中的path参数(即u'D:\Downloads')尝试了上面的代码片段-没有任何内存泄漏。哈哈。

根本原因是未能在非Unicode路径中的
路径
变量上调用
PyMem\u Free

    if (!PyArg_ParseTuple(args, "et:_isdir",
                          Py_FileSystemDefaultEncoding, &path))
        return NULL;

    attributes = GetFileAttributesA(path);
    if (attributes == INVALID_FILE_ATTRIBUTES)
        Py_RETURN_FALSE;

check:
    if (attributes & FILE_ATTRIBUTE_DIRECTORY)
        Py_RETURN_TRUE;
    else
        Py_RETURN_FALSE;
根据以下文件:

  • et
    :与
    es
    相同
  • es
    PyArg\u ParseTuple()
    将分配所需大小的缓冲区,将编码数据复制到此缓冲区,并调整*buffer以引用新分配的存储。调用者负责调用
    PyMem\u Free()
    以在使用后释放分配的缓冲区

这是Python标准库中的一个bug(在Python3中通过直接使用bytes对象修复);将错误报告提交到。

Hmm。。。这需要进一步调查。无论目录是否存在,我都会得到内存泄漏。Win7 64位上的Python 2.7.3。做得很好!也许值得向Python bug追踪器报告这一点!干得好!你一定要在bug追踪器上报告!另外,如果您提交一个带有bug报告的补丁(我认为在您的情况下,它只是
PyMem_Free(path)
之后
GetFileAttributesA
),那么您可以在
ACKS
文件::)中获得您的名字,因此它是函数的ASCII处理部分的一个bug。谢谢,分析到此结束!没错,它在技术上与Unicode/ASCII有关。调整了我的答案,谢谢。很好的分析工作。