Ich arbeite an einem plattformübergreifenden Python-Projekt. Es handelt sich um ein Befehlszeilentool mit automatischer Vervollständigung der Shell.setuptools fügt allen Skripten 150ms Startlatenz hinzu
Die Art und Weise setuptools
erzeugt die Konsole Skript mindestens 150ms Overhead ist imposant - manchmal mehr. Das ist einfach inakzeptabel für die Art von Werkzeug, das ich schreibe, und sollte nicht notwendig sein, da es im Grundfall wenig tut.
Ich versuche, beste Praxis für ein modernes Python-Projekt zu folgen, also verwende ich setuptools
das Projekt zu erstellen. Das Paket unterstützt Windows, daher ist es wichtig, Binär-Wrapper für Einstiegspunkte zu generieren.
Dies geschieht unabhängig davon, wie ich das Paket installieren - pip install
, pip install -e
, pip install --egg
, python setup.py install
usw.
Es gibt ein github issue das Problem diskutiert, aber keine Abhilfe oder Lösung so weit.
An anderer Stelle habe ich gesehen bewegt Menschen, weil dieser zu distutils zurück, aber das ist keine Option für mein Projekt.
Die einzige Problemumgehung, die ich mir vorstellen kann, ist irgendwie zu erweitern oder anzupassen, was setuptools
tut, wenn es nach Projekt installiert, so dass das binäre Shim pkg_resources
nicht verwendet.
Was kann ich kurz jener ziemlich drastische und unconstructive Maßnahme?
Mein setup.py
ist einfach - in etwa wie folgt:
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',
]
},
)
Die Scheibe, die für den Einstiegspunkt Setuptools erzeugt das wie folgt aussieht:
!$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')()
)
Hier sind einige cProfile
Statistiken die Setuptools verwenden -generiertes Konsolenskript:
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)
Und hier ist es als ein benutzerdefiniertes Skript ohne 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)
Die benutzerdefinierten Skript - test.py - ist sehr einfach:
from myproj.cli.myproj import main
main()
Also dann schreibe dein eigenes Skript. –
Wie würde ich es bereitstellen? Wenn setuptools etwas von "console_scripts" oder "scripts" bereitstellt, wird das Shim generiert, das 'load_entry_point()' verwendet, was langsam ist. – Cera