我试图用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
,但这失败了,因为它无法找到命令。
看起来我似乎误解了一些根本性的东西,但我无法弄清楚是什么。
答案 0 :(得分:5)
我最近与pex
进行了一些斗争,试图让它包含本地模块。我学到的是:
setup.py
文件才能实现此目的,并且:由于几个原因,这很难理解。通过阅读文档,我能够推断出我的案例中的正确命令应该是这样的:
$ pex . -v -e usersnotifier:main -o usersnotifier.pex
然而,当我尝试这个时,我不断收到错误说:
pex.resolvable.InvalidRequirement: Unknown requirement type: .
此错误的网络搜索会随着第一次点击 - this Github issue而显示 - 我输入时仍会打开。花了很长时间以为上面的命令因为这个bug而无法正常工作。我试图降级setuptools,并在this SO answer暗示提供setup.py
文件的必要性之前做了六次其他无效的尝试来“解决”问题。 (那个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_module
传递给setup()
而不是py_modules
(复数)。 ¯\ _(ツ)_ /¯
我遇到的最后一个障碍是在@cmcginty对这个问题的回答中提到的,即:除非您的模块版本号发生变化,否则pex
将从您上次运行它时缓存/重用工件。因此,如果您在setup.py
修复了问题并重新运行pex
,则除非您:a)碰撞版本号,或b)通过{{1},否则它实际上不会包含您的更改}在调用--disable-cache
时。
在一天结束时,整个过程变成了写一个合适的pex
并运行的练习:
setup.py
以下是我可以提供的一些提示(可能是我自己的未来版本):
使用$ pex . -v -e mymodule:main -o mymodule.pex --disable-cache
来测试您的python setup.py sdist
文件。令人惊讶的是 很容易搞砸了,在你确定你的包装有正确的内容之前,没有必要涉及setup.py
。运行pex
后,尝试将其生成的源包(位于python setup.py sdist
文件夹中)安装到新的venv中,看看它是否包含您期望的所有文件。只有在这个工作之后再继续调用dist
。
始终将pex
传递给--disable-cache
,除非您有充分理由不这样做。
在解决所有这些问题时,我发现我可以运行:
pex
提取PEX文件的内容。这有助于解决您的sdist包内容与您的pex-ified应用程序之间的任何差异。
答案 1 :(得分:2)
一种方法是:
python setup.py sdist
然后使用pex
开关
-f DIST_DIR
命令
例如。 pex $(pip freeze) -o aflaskapp.pex -e 'aflaskapp.app' -f dist -v
答案 2 :(得分:0)
我发现了一些其他细节。如果您运行:
pex .
它将尝试在目录中使用setup.py
版本。如果您没有,那么pex
将失败。
默认情况下,pex
会缓存本地包输出,因此如果您更改了setup.py
,请使用该命令确保在下一次pex
运行时应用更改。
pex . --disable-cache