用pex打包本地模块

cha*_*rly 5 python distutils build setuptools python-pex

我正在尝试将我的本地模块与pex打包在一起,但似乎无法解决。

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

? python --version
Python 2.7.10
? pex --version
pex 1.1.15
? tree .
.
??? bla
?   ??? __init__.py
?   ??? main.py
??? setup.py
Run Code Online (Sandbox Code Playgroud)

bla/__init__.py

import main
Run Code Online (Sandbox Code Playgroud)

bla/main.py

if __name__ == '__main__':
   print 'yo'
Run Code Online (Sandbox Code Playgroud)

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

? 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: .
Run Code Online (Sandbox Code Playgroud)

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

看来我似乎误解了一些基本知识,但我不知道是什么。

eva*_*low 7

我最近在pex尝试使其包含本地模块方面遇到了一些麻烦。我学到的是:

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

由于几个原因,很难弄清楚。通过阅读文档,我可以推断出我的情况下正确的命令应该是这样的:

$ pex . -v -e usersnotifier:main -o usersnotifier.pex
Run Code Online (Sandbox Code Playgroud)

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

pex.resolvable.InvalidRequirement: Unknown requirement type: .
Run Code Online (Sandbox Code Playgroud)

在网络上搜索此错误(这是第一个命中)的- 这个Github问题,在我键入此问题时仍然打开。A花费了很长时间思考以上命令由于此错误而无法正常工作。我试图降级setuptools,并进行了六次其他无济于事的尝试来“解决”该问题,然后该SO答案提示必须提供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'
Run Code Online (Sandbox Code Playgroud)

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
)
Run Code Online (Sandbox Code Playgroud)

它之前没有起作用的原因是我不小心将参数传递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
Run Code Online (Sandbox Code Playgroud)

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

提示1

使用python setup.py sdist来测试你的setup.py文件。这是令人惊讶的容易搞砸,而且也没有涉及点pex,直到你确信你的包有正确的内容。运行后python setup.py sdist,尝试将其生成的源程序包(位于dist文件夹中)安装到新的venv中,并查看其是否包含所需的所有文件。只有pex 在进行此操作才能继续进行调用。

提示2

除非您有充分的理由不这样做--disable-cachepex否则请务必通过。

提示3

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

$ unzip mymodule.pex
Run Code Online (Sandbox Code Playgroud)

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