7

我正在尝试用 pex 打包我的本地模块,但我似乎无法做到。

我创建了一个简单的项目:

→ python --version
Python 2.7.10
→ pex --version
pex 1.1.15
→ tree .
.
├── bla
│   ├── __init__.py
│   └── main.py
└── setup.py

bla/__init__.py

import main

bla/main.py

if __name__ == '__main__':
   print 'yo'

在我看来,这似乎是最简单的项目。

→ pex -v . -o v.pex --disable-cache
Traceback (most recent call last):
  File "/Users/Charly/repos/load_tester/venv/bin/pex", line 11, in <module>
   sys.exit(main())
 File "/Users/Charly/repos/load_tester/venv/lib/python2.7/site-packages/pex/bin/pex.py", line 540, in main
    pex_builder = build_pex(reqs, options, resolver_options_builder)
 File "/Users/Charly/repos/load_tester/venv/lib/python2.7/site-packages/pex/bin/pex.py", line 475, in build_pex
    resolvables = [Resolvable.get(arg, resolver_option_builder) for arg in args]
  File "/Users/Charly/repos/load_tester/venv/lib/python2.7/site-packages/pex/resolvable.py", line 61, in get
    raise cls.InvalidRequirement('Unknown requirement type: %s' % resolvable_string)
 pex.resolvable.InvalidRequirement: Unknown requirement type: .

也尝试过这样做python setup.py bdist_pex,但是失败了,并且找不到命令。

看起来我真的误解了一些基本的东西,但我不知道是什么。

4

3 回答 3

11

我最近在pex尝试让它包含本地模块时遇到了一些困难。我学到的是:

  1. 必须为您的模块提供有效的setup.py文件才能使其正常工作,并且:
  2. 必须指定应用程序的入口点

由于几个原因,这很难弄清楚。通过阅读文档,我能够推断出在我的案例中正确的命令应该是这样的:

$ pex . -v -e usersnotifier:main -o usersnotifier.pex

但是,当我尝试这个时,我不断收到错误消息:

pex.resolvable.InvalidRequirement: Unknown requirement type: .

出现了对这个错误的网络搜索——作为它的第一个命中——<a href="https://github.com/pantsbuild/pex/issues/360" rel="noreferrer">这个 Github 问题,它仍然以我打这个。由于这个错误,A 花了很长时间认为上述命令不起作用。在此 SO 答案暗示有必要提供setup.py文件之前,我尝试降级 setuptools 并进行了六次其他徒劳的尝试来“解决”问题。(那个 Github 问题原来是一个红鲱鱼。setuptools它提到的错误已经被修复,据我所知。)

所以...我写了一个setup.py文件。起初,我一直在说那个错误,Unknown requirement type: .但后来我意识到我setup.py只是包含一个非常明显的印刷错误。在这种情况下,pex 发出的错误消息实际上很清楚,但后面跟着一个大的堆栈跟踪和Unknown requirement type: .消息。我只是没有密切关注,错过的时间比我愿意承认的要长。

我终于注意到我的错字并修复了它,但我的另一个缺陷setup.py是未能包含我的本地模块。pex在这种情况下工作,但生成的文件没有:

$ pex . -v -e usersnotifier:main -o usersnotifier.pex --disable-cache                                                                                                                     
  usersnotifier 0.1: Resolving distributions :: Packaging paho-mqtt    
  pyinotify 0.9.6
  paho-mqtt 1.3.1
pex: Building pex: 2704.3ms                                        
pex:   Resolving distributions: 2393.2ms
pex:       Packaging usersnotifier: 319.3ms
pex:       Packaging pyinotify: 347.4ms
pex:       Packaging paho-mqtt: 361.1ms
Saving PEX file to usersnotifier.pex

$ ./usersnotifier.pex 
Traceback (most recent call last):
  File ".bootstrap/_pex/pex.py", line 367, in execute
  File ".bootstrap/_pex/pex.py", line 293, in _wrap_coverage
  File ".bootstrap/_pex/pex.py", line 325, in _wrap_profiling
  File ".bootstrap/_pex/pex.py", line 410, in _execute
  File ".bootstrap/_pex/pex.py", line 468, in execute_entry
  File ".bootstrap/_pex/pex.py", line 482, in execute_pkg_resources
  File ".bootstrap/pkg_resources/__init__.py", line 2297, in resolve
ImportError: No module named 'usersnotifier'

setup.py这是最终为我工作的准系统:

from setuptools import setup                                                                                                                                                              

setup(
    name='usersnotifier',
    version='0.1',
    py_modules=['usersnotifier', 'userswatcher'],
    install_requires=[
        'paho-mqtt>=1.3.1',
        'pyinotify>=0.9.6',
    ],
    include_package_data=True,
    zip_safe=False
)

它以前不起作用的原因是我不小心将参数传递py_modulesetup()而不是py_modules(复数)。¯\_(ツ)_/¯

@cmcginty 对这个问题的回答中提到了我遇到的最后一个障碍,即:除非您的模块版本号发生更改,pex否则将缓存/重用您上次运行它的工件。因此,如果您修复了您的问题setup.py并重新运行pex,它实际上不会合并您的更改,除非您:a)增加版本号,或 b)--disable-cache在调用pex.

在一天结束时,整个事情变成了编写正确的练习setup.py,并运行:

$ pex . -v -e mymodule:main -o mymodule.pex --disable-cache

以下是我可以提供的一些提示(可能是我未来的版本):

提示 1

用于python setup.py sdist测试您的setup.py文件。搞砸这件事出奇地容易,在你确定你的包裹有正确的内容之前,没有任何意义pex。运行后python setup.py sdist,尝试将它生成的源包(位于dist文件夹中)安装到一个新的 venv 中,看看它是否包含您期望的所有文件。只有在这工作pex 之后才继续调用。

提示 2

除非您有充分的理由不这样做,否则请始终传递--disable-cache给。pex

提示 3

在对所有这些问题进行故障排除时,我发现我可以运行:

$ unzip mymodule.pex

提取 PEX 文件的内容。这有助于解决 sdist 包内容和 pex 化应用程序之间存在的任何差异。

于 2018-03-29T22:03:08.743 回答
3

一种方法是:

  1. 使用创建源分发(tarball、zip 文件等)python setup.py sdist
  2. 然后用开关运行pex命令-f DIST_DIR

    例如。pex $(pip freeze) -o aflaskapp.pex -e 'aflaskapp.app' -f dist -v

于 2016-11-09T06:03:24.000 回答
0

我发现了一些额外的细节。如果你运行:

pex .

它将尝试使用setup.py目录中的构建。如果你没有那个,那么pex就会失败。

默认情况下,pex将缓存本地包输出,因此如果您更改您的setup.pythen 使用命令确保您的更改在下次pex运行时应用。

pex . --disable-cache
于 2018-03-21T18:33:30.867 回答