python - setuptools 为所有脚本增加了 150 毫秒的启动延迟

标签 python setuptools packaging

我正在从事一个跨平台的 Python 项目。它是具有 shell 自动完成功能的命令行工具,因此速度很重要。

方式setuptools生成控制台脚本至少需要 150 毫秒的开销——有时更多。这对于我正在编写的那种工具来说是完全不能接受的,而且考虑到它在基本情况下的作用很少,所以没有必要。

我正在尝试遵循现代 Python 项目的最佳实践,所以我正在使用 setuptools构建项目。该包支持 Windows,因此它为入口点生成二进制包装器的能力至关重要。

无论我如何安装包,都会发生这种情况 - pip install , pip install -e , pip install --egg , python setup.py install

有一个 github issue讨论了问题,但目前还没有解决方法或解决方案。

我在其他地方看到人们因此而回到 distutils,但这不是我项目的选择。

我能想到的唯一解决方法是以某种方式扩展或自定义 setuptools 的内容当它按项目安装时执行,以便二进制 shim 不使用 pkg_resources .

除了这种相当激烈和非建设性的措施,我还能做什么?


我的 setup.py是基本的——大致如下:

import pip.req
import setuptools

def install_reqs():
    reqs = pip.req.parse_requirements('requirements.txt', session=False)
    reqs = [str(ir.req) for ir in reqs]
    return reqs

setuptools.setup(
    name='myproj',
    version='v1.0.0-dev',
    packages=setuptools.find_packages(exclude=('tests')),
    install_requires=install_reqs(),
    include_package_data=True,
    entry_points={
        'console_scripts': [
            'myproj = myproj.cli.myproj:main',
        ]
    },
)

setuptools 为入口点生成的 shim 如下所示:

!$myhome/.venv/myproj/bin/python
# EASY-INSTALL-ENTRY-SCRIPT: 'myproj==1.0.0.dev0','console_scripts','myproj'
__requires__ = 'myproj==1.0.0.dev0'
import sys
from pkg_resources import load_entry_point

if __name__ == '__main__':
    sys.exit(
        load_entry_point('myproj==1.0.0.dev0', 'console_scripts', 'myproj')()
    )

这里有一些 cProfile使用 setuptools 生成的控制台脚本的统计信息:

ncalls  tottime  percall  cumtime  percall filename:lineno(function)
121/1    0.015    0.000    0.278    0.278 {built-in method builtins.exec}
    1    0.000    0.000    0.278    0.278 myproj:3(<module>)
125/3    0.001    0.000    0.221    0.074 <frozen importlib._bootstrap>:966(_find_and_load)
125/3    0.001    0.000    0.221    0.074 <frozen importlib._bootstrap>:939(_find_and_load_unlocked)
125/5    0.001    0.000    0.219    0.044 <frozen importlib._bootstrap>:659(_load_unlocked)
 99/5    0.001    0.000    0.219    0.044 <frozen importlib._bootstrap_external>:656(exec_module)
152/4    0.000    0.000    0.218    0.054 <frozen importlib._bootstrap>:214(_call_with_frames_removed)
    2    0.000    0.000    0.204    0.102 __init__.py:15(<module>)
32/15    0.000    0.000    0.135    0.009 {built-in method builtins.__import__}
    1    0.000    0.000    0.088    0.088 __init__.py:540(load_entry_point)
    1    0.000    0.000    0.085    0.085 __init__.py:2564(load_entry_point)
    1    0.000    0.000    0.083    0.083 __init__.py:2216(load)

这里是没有 setuptools shim 的自定义脚本:

ncalls  tottime  percall  cumtime  percall filename:lineno(function)
 58/1    0.006    0.000    0.053    0.053 {built-in method builtins.exec}
    1    0.000    0.000    0.053    0.053 test.py:1(<module>)
 53/3    0.000    0.000    0.052    0.017 <frozen importlib._bootstrap>:966(_find_and_load)
 53/3    0.000    0.000    0.052    0.017 <frozen importlib._bootstrap>:939(_find_and_load_unlocked)
 53/5    0.000    0.000    0.051    0.010 <frozen importlib._bootstrap>:659(_load_unlocked)
 65/4    0.000    0.000    0.051    0.013 <frozen importlib._bootstrap>:214(_call_with_frames_removed)
 45/5    0.000    0.000    0.051    0.010 <frozen importlib._bootstrap_external>:656(exec_module)

自定义脚本 - test.py - 非常简单:

from myproj.cli.myproj import main

main()

最佳答案

如果我使用“pip install .”从源代码安装项目,我也遇到过这个问题。但是,如果我先构建一个二进制 wheel 文件然后安装 wheel,生成的 shim 似乎不使用 pkg_resources 并且速度更快。我已经使用 cookiecutter 项目对此进行了测试:

https://github.com/audreyr/cookiecutter

如果我克隆这个项目,然后使用原始方法“pip install”进行安装,生成的可执行脚本包含从 pkg_resources 导入(速度很慢):

#!/usr/local/opt/python3/bin/python3.5
# EASY-INSTALL-ENTRY-SCRIPT: 'cookiecutter==1.5.1','console_scripts','cookiecutter'
__requires__ = 'cookiecutter==1.5.1'
import re
import sys
from pkg_resources import load_entry_point

if __name__ == '__main__':
    sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
    sys.exit(
        load_entry_point('cookiecutter==1.5.1', 'console_scripts', 'cookiecutter')()
    )

但是,如果我执行以下两个命令:

python setup.py bdist_wheel
pip install dist/cookiecutter-1.5.1-py2.py3-none-any.whl

生成的 shim 不包含 pkg_resources(而且速度更快):

#!/usr/local/opt/python3/bin/python3.5

# -*- coding: utf-8 -*-
import re
import sys

from cookiecutter.__main__ import main

if __name__ == '__main__':
    sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
    sys.exit(main())

当我在 Windows 上尝试后一种方法时,它仍然创建了 .exe 填充程序。

关于python - setuptools 为所有脚本增加了 150 毫秒的启动延迟,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38279083/

相关文章:

python - 清除 Pyramid 中的设置工具缓存?

PHP 作为独立应用程序(二进制、编译、打包、主机上没有 php)

linux - 如何知道RPM中内置宏的值?

python - 如何使用 Turtle Graphic 绘制单个点

python - 对于 Django 模型,是否有查看记录是否存在的快捷方式?

setuptools - 是否有理由在 python 项目中同时拥有 tox.ini 和 setup.cfg?

python - 让我的 Python 包在“开始”菜单中安装快捷方式

linux - 如何使用 GNU Automake 后安装某些东西?

python - HTTP 摘要认证 python

python - 斯坦福 CoreNLP OpenIE 注释器