【问题标题】:When I run the setuptools .egg "as if it were a shell script", what's actually happening?当我运行 setuptools .egg “就好像它是一个 shell 脚本”时,实际发生了什么?
【发布时间】:2012-11-04 03:31:50
【问题描述】:

通过阅读this documentation,我已经建立了sh setuptools-0.6c11-py2.7.egg 命令实际作用的心智模型,但它非常不完整,我仍然对某些方面感到困惑。

我的心智模型是这样的:

  1. 发出此命令后,egg(我认为它是一种巧妙处理依赖关系的 zip 文件)以某种方式在我的系统上找到了正确版本的 python,并使用该 python,“自行安装”到合适的位置。
  2. 实际上,这意味着一个名为easy_install 的“Unix 可执行文件”创建在一个目录中,该目录希望位于我的路径上。这就是为什么我之后可以在终端中输入easy_install somepackage

因此我的问题是:

  1. “蛋”如何以这种方式“自我安装”?当其他鸡蛋需要 easy_install 才能工作时,为什么这对这个鸡蛋特别有效?
  2. 由此创建的“Unix 可执行文件”为 4kb。它究竟是什么?它充满了对其他事物的调用吗?他们在哪里?

这不是一个“如何让它工作”的问题——我在这个轴上没有任何问题,但我想完全了解这里发生了什么。

【问题讨论】:

    标签: python shell setuptools easy-install


    【解决方案1】:

    Egg 文件是简单的 zip 压缩目录,包含 Python 包、模块和一些元数据,扩展名为 .egg

    zip格式灵活;它将忽略文件开头 不是 zipfile 一部分的任何内容。通过查找一系列字符(PK 和另外两个指示类型的字节)并从那里读取来检测 zipfile。

    这意味着您可以在拉链的 前面 放一些东西。 setuptools Eggs 的特殊之处在于它们使用这个技巧在 zip 数据之前插入一些 shell 脚本:

    $ 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
    

    经过前 8 行,这是一个真正的 zip:

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

    前 8 行中包含的脚本是您运行 sh setuptools-0.6c11-py2.7.egg 时正在执行的脚本。

    如您所见,脚本是特定于 egg 版本的;这在 python 2.7 的版本中,它只是使用 python 解释器将这个 egg 添加到 python 搜索路径。然后它从包含的 python 模块中导入一个函数并运行它。

    这是鸡蛋本身的内容,正如我提到的,它只是一个 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%
    

    【讨论】:

    • 这是一个令人瞠目结舌的快速而完整的答案,我觉得我现在完全明白了。你以前回答过我的问题,而且很有帮助,但这个答案真的很特别——谢谢!
    • shell如何知道在前8行之后停止解析文件?
    • @jpmc26: exec 告诉 shell 用新进程替换自己。该脚本总是会到达两个exec 命令之一,因此这是shell 执行结束的地方,Python 二进制文件将接管,或者false 被执行(然后以非零代码退出)。
    猜你喜欢
    • 1970-01-01
    • 2021-06-27
    • 2016-02-16
    • 1970-01-01
    • 2017-09-22
    • 2011-06-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多