用pex封装本地模块

2024-05-29 02:20:30 发布

您现在位置:Python中文网/ 问答频道 /正文

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

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

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

bla/__init__.py

^{pr2}$

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,但失败了,因为找不到命令。在

我好像真的误解了一些基本的东西,但我不知道是什么。在


Tags: inpybinvenvmainliblineload
3条回答

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

pex .

它将尝试使用目录中的setup.py内部版本。如果没有,则pex将失败。在

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

^{pr2}$

我最近与pex进行了一场斗争,试图让它包含本地模块。我学到的是:

  1. 您必须为您的模块提供一个有效的setup.py文件,然后:
  2. 必须指定应用程序的入口点

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

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

然而,当我试着这样做时,我总是得到一个错误,说:

^{pr2}$

一个针对这个错误的web搜索出现在它的第一个命中-this Github issue,在我输入这个时它仍然是打开的。A花了很长时间认为上面的命令因为这个错误而无效。在this SO answer暗示有必要提供^{cd2>}文件之前,我试图降低setuptools的级别,并尝试“修复”这个问题。(Github的问题最终被证明是一个红鲱鱼。据我所知,它提到的setuptools错误已经被修复了。)

所以。。。我写了一个setup.py文件。一开始,我一直收到这样一个错误,说Unknown requirement type: .,但后来我意识到我的setup.py只是包含了一个非常明显的排版错误。在本例中,pex发出的错误消息实际上非常清楚,但是后面是一个很大的ish堆栈跟踪和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'

以下是最终对我有用的基本知识:

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(),而不是{}(复数)。` \(ツ)´´

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

最后,整个过程变成了一个练习,写一个合适的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-ified应用程序之间的任何差异。在

一种方法是:

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

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

相关问题 更多 >

    热门问题