4 votes

setuptools ajoute 150ms de latence au démarrage à tous les scripts.

Je travaille sur un projet Python multiplateforme. Il s'agit d'un outil en ligne de commande avec autocomplétion de l'interpréteur de commandes, donc la vitesse est importante.

La manière setuptools génère la console script impose au moins 150ms de surcharge - parfois plus. C'est tout simplement inacceptable pour le genre d'outil que j'écris, et ne devrait pas être nécessaire étant donné le peu qu'il fait dans le cas de base.

J'essaie de suivre les meilleures pratiques d'un projet Python moderne, et j'utilise donc setuptools pour construire le projet. Le paquetage supporte Windows, donc sa capacité à générer des wrappers binaires pour les points d'entrée est essentielle.

Cela se produit quelle que soit la façon dont j'installe le paquet - pip install , pip install -e , pip install --egg , python setup.py install etc.

Il y a un numéro github discutant du problème, mais pas de solution de contournement ou de solution jusqu'à présent.

Ailleurs, j'ai vu des gens revenir à distutils pour cette raison, mais ce n'est pas une option pour mon projet.

La seule solution à laquelle je pense est d'étendre ou de personnaliser d'une manière ou d'une autre ce qui suit setuptools fait quand il installe par projet pour que le shim binaire n'utilise pas pkg_resources .

Que puis-je faire en dehors de cette mesure assez radicale et peu constructive ?


Mon setup.py est basique - à peu près comme suit :

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',
        ]
    },
)

La cale que setuptools génère pour le point d'entrée ressemble à ceci :

!$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')()
    )

Voici quelques cProfile stats en utilisant la console générée par setuptools script :

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)

Et le voici en tant que script personnalisé sans la cale setuptools :

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)

Le script personnalisé - test.py - est très simple :

from myproj.cli.myproj import main

main()

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X