Cuando ejecuto el archivo setuptools.egg “como si fuera un script de shell”, ¿qué sucede realmente?

Al leer esta documentación , he creado un modelo mental de lo que realmente hace el comando sh setuptools-0.6c11-py2.7.egg , pero está muy incompleto y todavía estoy desconcertado por algunos aspectos.

Mi modelo mental es algo así:

  1. Cuando se emite este comando, el huevo (que consideré como una especie de archivo zip que maneja inteligentemente las dependencias) de alguna manera encuentra la versión correcta de python en mi sistema, y ​​al usar ese python, “se instala a sí mismo” en una ubicación apropiada.
  2. En la práctica, esto significa que un ‘Archivo ejecutable de Unix’ llamado easy_install se crea en un directorio que es de esperar en mi ruta. Esta es la razón por la que simplemente puedo escribir easy_install somepackage en el terminal después.

Mis preguntas son por lo tanto:

  1. ¿Cómo es posible que un ‘huevo’ se “instale” de esta manera? ¿Por qué esto funciona para este huevo en particular, cuando otros huevos requieren que easy_install funcione?
  2. El ‘Archivo ejecutable de Unix’ creado de este modo es 4kb. ¿Qué es en realidad? ¿Está lleno de llamadas a otras cosas? ¿Dónde están?

Esta no es una pregunta de ‘cómo hacer que funcione’. No tengo ningún problema en ese eje, pero me gustaría asimilar por completo lo que está sucediendo aquí.

Los archivos de Egg son simplemente directorios comprimidos en zip que contienen paquetes, módulos y pequeños metadatos de Python, con una extensión .egg .

El formato zip es flexible; ignorará cualquier cosa al inicio del archivo que no sea parte del archivo zip. El archivo zip se detecta al encontrar una serie de caracteres ( PK y dos bytes más que indican el tipo) y leer desde allí.

Esto significa que puedes poner algo delante de la cremallera. Los huevos de setuptools son especiales porque utilizan este truco para insertar un script de shell antes de los datos zip:

 $ head -n8 setuptools-0.6c11-py2.7.egg #!/bin/sh if [ `basename $0` = "setuptools-0.6c11-py2.7.egg" ] then exec python2.7 -c "import sys, os; sys.path.insert(0, os.path.abspath('$0')); from setuptools.command.easy_install import bootstrap; sys.exit(bootstrap())" "$@" else echo $0 is not the correct name for this egg file. echo Please rename it back to setuptools-0.6c11-py2.7.egg and try again. exec false fi 

Pasadas esas primeras 8 líneas, es un auténtico zip:

 $ tail -n+9 setuptools-0.6c11-py2.7.egg | file - /dev/stdin: Zip archive data, at least v2.0 to extract 

El script contenido en esas primeras 8 líneas es lo que se ejecuta cuando ejecutas sh setuptools-0.6c11-py2.7.egg .

Como puede ver, el script es específico para la versión de egg; esto en la versión para python 2.7, y simplemente usa el intérprete de python para agregar este huevo a la ruta de búsqueda de python. Luego importa una función del módulo de python contenido y la ejecuta.

Aquí están los contenidos del huevo, que es como mencioné solo un archivo zip:

 $ zipinfo -l setuptools-0.6c11-py2.7.egg Archive: setuptools-0.6c11-py2.7.egg 332005 bytes 78 files -rw-rw-r-- 2.0 unx 1713 b- 995 defN 7-Jul-10 20:26 site.pyc -rw-rw-r-- 2.0 unx 90113 b- 31461 defN 7-Jul-10 20:26 pkg_resources.pyc -rw-rw-r-- 2.0 unx 85435 b- 23537 defN 19-Oct-09 13:35 pkg_resources.py -rw-rw-r-- 2.0 unx 2362 b- 875 defN 20-Sep-06 17:05 site.py -rw-rw-r-- 2.0 unx 309 b- 224 defN 7-Jul-10 20:26 easy_install.pyc -rw-rw-r-- 2.0 unx 126 b- 105 defN 20-Sep-06 17:05 easy_install.py -rw-rw-r-- 2.0 unx 43 b- 43 defN 7-Jul-10 20:26 EGG-INFO/top_level.txt -rw-rw-r-- 2.0 unx 1591 b- 458 defN 7-Jul-10 20:26 EGG-INFO/SOURCES.txt -rw-rw-r-- 2.0 unx 1 b- 3 defN 20-Oct-09 10:07 EGG-INFO/zip-safe -rw-rw-r-- 2.0 unx 9278 b- 3194 defN 7-Jul-10 20:26 EGG-INFO/PKG-INFO -rwxrwxr-x 2.0 unx 2504 b- 623 defN 7-Jul-10 20:26 EGG-INFO/entry_points.txt -rw-rw-r-- 2.0 unx 1 b- 3 defN 7-Jul-10 20:26 EGG-INFO/dependency_links.txt -rw-rw-r-- 2.0 unx 1567 b- 791 defN 7-Jul-10 20:26 setuptools/extension.pyc -rw-rw-r-- 2.0 unx 1089 b- 424 defN 20-Sep-06 17:05 setuptools/extension.py -rw-rw-r-- 2.0 unx 10796 b- 4050 defN 7-Jul-10 20:26 setuptools/sandbox.pyc -rw-rw-r-- 2.0 unx 8227 b- 2309 defN 6-Jul-10 20:09 setuptools/sandbox.py -rw-rw-r-- 2.0 unx 5677 b- 2499 defN 7-Jul-10 20:26 setuptools/archive_util.pyc -rw-rw-r-- 2.0 unx 26800 b- 11228 defN 7-Jul-10 20:26 setuptools/package_index.pyc -rw-rw-r-- 2.0 unx 6209 b- 2229 defN 19-Oct-09 13:35 setuptools/depends.py -rw-rw-r-- 2.0 unx 6677 b- 3096 defN 7-Jul-10 20:26 setuptools/depends.pyc -rw-rw-r-- 2.0 unx 2816 b- 1159 defN 6-Jul-10 20:09 setuptools/__init__.py -rw-rw-r-- 2.0 unx 3639 b- 1837 defN 7-Jul-10 20:26 setuptools/__init__.pyc -rw-rw-r-- 2.0 unx 5924 b- 1777 defN 19-Oct-09 13:35 setuptools/archive_util.py -rw-rw-r-- 2.0 unx 29972 b- 8156 defN 19-Oct-09 13:35 setuptools/dist.py -rwxrwxr-x 2.0 unx 7168 b- 3249 defN 19-Oct-09 17:18 setuptools/cli.exe -rw-rw-r-- 2.0 unx 28275 b- 8698 defN 6-Jul-10 20:09 setuptools/package_index.py -rw-rw-r-- 2.0 unx 29786 b- 10953 defN 7-Jul-10 20:26 setuptools/dist.pyc -rwxrwxr-x 2.0 unx 7168 b- 3244 defN 19-Oct-09 17:18 setuptools/gui.exe -rw-rw-r-- 2.0 unx 22219 b- 7042 defN 7-Jul-10 20:26 setuptools/tests/test_resources.pyc -rw-rw-r-- 2.0 unx 19388 b- 4723 defN 24-Sep-08 13:10 setuptools/tests/test_resources.py -rw-rw-r-- 2.0 unx 12345 b- 2765 defN 24-Sep-08 13:10 setuptools/tests/__init__.py -rw-rw-r-- 2.0 unx 13811 b- 4523 defN 7-Jul-10 20:26 setuptools/tests/__init__.pyc -rw-rw-r-- 2.0 unx 1499 b- 708 defN 7-Jul-10 20:26 setuptools/tests/test_packageindex.pyc -rw-rw-r-- 2.0 unx 81351 b- 27171 defN 7-Jul-10 20:26 setuptools/tests/doctest.pyc -rw-rw-r-- 2.0 unx 759 b- 346 defN 24-Sep-08 13:10 setuptools/tests/test_packageindex.py -rw-rw-r-- 2.0 unx 99714 b- 25663 defN 20-Sep-06 17:05 setuptools/tests/doctest.py -rw-rw-r-- 2.0 unx 2866 b- 1332 defN 7-Jul-10 20:26 setuptools/command/rotate.pyc -rw-rw-r-- 2.0 unx 11520 b- 3127 defN 19-Oct-09 13:35 setuptools/command/build_ext.py -rw-rw-r-- 2.0 unx 6649 b- 2208 defN 24-Sep-08 13:10 setuptools/command/upload.py -rw-rw-r-- 2.0 unx 8162 b- 3538 defN 7-Jul-10 20:26 setuptools/command/sdist.pyc -rw-rw-r-- 2.0 unx 5965 b- 2421 defN 7-Jul-10 20:26 setuptools/command/setopt.pyc -rw-rw-r-- 2.0 unx 2283 b- 695 defN 19-Oct-09 17:50 setuptools/command/bdist_wininst.py -rw-rw-r-- 2.0 unx 7535 b- 3208 defN 7-Jul-10 20:26 setuptools/command/build_py.pyc -rw-rw-r-- 2.0 unx 3690 b- 1528 defN 7-Jul-10 20:26 setuptools/command/install.pyc -rw-rw-r-- 2.0 unx 14205 b- 4465 defN 19-Oct-09 13:35 setuptools/command/egg_info.py -rw-rw-r-- 2.0 unx 626 b- 311 defN 28-Dec-06 19:52 setuptools/command/__init__.py -rw-rw-r-- 2.0 unx 839 b- 494 defN 7-Jul-10 20:26 setuptools/command/__init__.pyc -rw-rw-r-- 2.0 unx 5053 b- 1519 defN 20-Sep-06 17:05 setuptools/command/setopt.py -rw-rw-r-- 2.0 unx 674 b- 329 defN 7-Jul-10 20:26 setuptools/command/register.pyc -rw-rw-r-- 2.0 unx 3724 b- 1292 defN 4-Sep-07 00:11 setuptools/command/install_egg_info.py -rw-rw-r-- 2.0 unx 18005 b- 5444 defN 19-Oct-09 13:35 setuptools/command/bdist_egg.py -rw-rw-r-- 2.0 unx 3984 b- 1385 defN 15-Feb-08 12:29 setuptools/command/install.py -rw-rw-r-- 2.0 unx 2356 b- 1002 defN 7-Jul-10 20:26 setuptools/command/bdist_wininst.pyc -rw-rw-r-- 2.0 unx 2025 b- 774 defN 22-May-07 17:55 setuptools/command/bdist_rpm.py -rw-rw-r-- 2.0 unx 2486 b- 871 defN 20-Sep-06 17:05 setuptools/command/install_lib.py -rw-rw-r-- 2.0 unx 740 b- 357 defN 20-Sep-06 17:05 setuptools/command/saveopts.py -rw-rw-r-- 2.0 unx 56980 b- 23198 defN 7-Jul-10 20:26 setuptools/command/easy_install.pyc -rw-rw-r-- 2.0 unx 3172 b- 1438 defN 7-Jul-10 20:26 setuptools/command/install_lib.pyc -rw-rw-r-- 2.0 unx 2257 b- 1013 defN 7-Jul-10 20:26 setuptools/command/bdist_rpm.pyc -rw-rw-r-- 2.0 unx 5310 b- 1732 defN 15-Feb-08 12:29 setuptools/command/develop.py -rw-rw-r-- 2.0 unx 5091 b- 2222 defN 7-Jul-10 20:26 setuptools/command/test.pyc -rw-rw-r-- 2.0 unx 63580 b- 17507 defN 19-Oct-09 13:35 setuptools/command/easy_install.py -rw-rw-r-- 2.0 unx 16467 b- 6544 defN 7-Jul-10 20:26 setuptools/command/egg_info.pyc -rw-rw-r-- 2.0 unx 4577 b- 1994 defN 7-Jul-10 20:26 setuptools/command/install_egg_info.pyc -rw-rw-r-- 2.0 unx 6275 b- 3108 defN 7-Jul-10 20:26 setuptools/command/upload.pyc -rw-rw-r-- 2.0 unx 7246 b- 2237 defN 20-Sep-06 17:05 setuptools/command/build_py.py -rw-rw-r-- 2.0 unx 10073 b- 4314 defN 7-Jul-10 20:26 setuptools/command/build_ext.pyc -rw-rw-r-- 2.0 unx 3185 b- 1463 defN 7-Jul-10 20:26 setuptools/command/alias.pyc -rw-rw-r-- 2.0 unx 1921 b- 704 defN 15-Feb-08 12:29 setuptools/command/install_scripts.py -rw-rw-r-- 2.0 unx 7327 b- 2380 defN 19-Oct-09 15:46 setuptools/command/sdist.py -rw-rw-r-- 2.0 unx 1249 b- 647 defN 7-Jul-10 20:26 setuptools/command/saveopts.pyc -rw-rw-r-- 2.0 unx 2021 b- 750 defN 20-Sep-06 17:05 setuptools/command/rotate.py -rw-rw-r-- 2.0 unx 2477 b- 848 defN 19-Oct-09 13:35 setuptools/command/alias.py -rw-rw-r-- 2.0 unx 17695 b- 7800 defN 7-Jul-10 20:26 setuptools/command/bdist_egg.pyc -rw-rw-r-- 2.0 unx 277 b- 158 defN 20-Sep-06 17:05 setuptools/command/register.py -rw-rw-r-- 2.0 unx 4442 b- 1424 defN 15-Feb-08 12:29 setuptools/command/test.py -rw-rw-r-- 2.0 unx 2445 b- 1160 defN 7-Jul-10 20:26 setuptools/command/install_scripts.pyc -rw-rw-r-- 2.0 unx 5175 b- 2317 defN 7-Jul-10 20:26 setuptools/command/develop.pyc 78 files, 958981 bytes uncompressed, 321419 bytes compressed: 66.5%