如何避免 Pip 在可编辑模式下安装的脚本生成 "ResourceWarning: unclosed file" 消息?

How to avoid scripts installed by Pip in editable mode generating "ResourceWarning: unclosed file" messages?

当使用 "pip" 以可编辑模式(使用“-e”)标志安装包时,任何可执行脚本在调用时都会产生恼人的 "ResourceWarning: unclosed file " 消息。

要重现,请考虑以下最小包:

foo/
    bin/foo.py
    setup.py

其中 "setup.py" 有:

#! /usr/bin/env python
# -*- coding: utf-8 -*-

from setuptools import setup

setup(
    name='foo',
    version='0.1',
    scripts=["bin/foo.py"],
    zip_safe=False)

和"bin/foo.py"有,例如

#! /usr/bin/env python
# -*- coding: utf-8 -*-

print("hello, world")

然后,运行:

python3 -m pip install -e foo

调用可执行结果:

$ foo.py 
/.../bin/foo.py:6: ResourceWarning: unclosed file <_io.TextIOWrapper name='/.../foo/bin/foo.py' mode='r' encoding='UTF-8'>
hello, world

问题是 "pip" 在可编辑模式下自动生成并安装在用户二进制目录中的虚拟脚本存根使用以下语句调用源脚本:

exec(compile(open(__file__).read(), __file__, 'exec'))

确实打开了文件,但没有关闭。手动修复它很简单。但是我们如何让"pip"自己正确地做呢?

(注意,不使用"editable"模式时不会出现此问题,因为这里直接复制可执行脚本,而不是通过包装脚本调用)。

尝试:

您将在站点包目录中找到模板,文件名为 script (dev).tmpl:

$ cat ".venv/lib/python3.6/site-packages/setuptools/script (dev).tmpl"
# EASY-INSTALL-DEV-SCRIPT: %(spec)r,%(script_name)r
__requires__ = %(spec)r
__import__('pkg_resources').require(%(spec)r)
__file__ = %(dev_path)r
exec(compile(open(__file__).read(), __file__, 'exec'))

根据需要进行编辑,例如:

# EASY-INSTALL-DEV-SCRIPT: %(spec)r,%(script_name)r
__requires__ = %(spec)r
__import__('pkg_resources').require(%(spec)r)
__file__ = %(dev_path)r
try:
    f = open(__file__)
    exec(compile(f.read(), __file__, 'exec'))
finally:
    f.close()

最后:

对拉取请求投票:https://github.com/pypa/setuptools/pull/1398 这几乎是立即合并的,因此模板应该在下一个 setuptools 版本中修复。似乎这里唯一需要的是有人足够关心实际抱怨它。