我无法获得编译后的python脚本所能看到的其他可用模块。为了接受基于venv的模块或全局模块,我需要如何更改以下流程?在
步骤:
$ python3 -m venv sometest
$ cd sometest
$ . bin/activate
(sometest) $ pip3 install PyCrypto Cython
基本脚本,使用非标准模块Crypto
:
(sometest) $ python3 hello.py
The answer is no
b'1oONZCFWVJKqYEEF4JuL8Q=='
编译它:
(sometest) $ cython -3 --embed hello.py
(sometest) $ gcc -Os -I /usr/include/python3.5m -o hello hello.c -lpython3.5m -lpthread -lm -lutil -ldl
(sometest) $ $ ./hello
Traceback (most recent call last):
File "hello.py", line 1, in init hello
from Crypto.Cipher import AES
ImportError: No module named 'Crypto'
我不认为使用cython嵌入式编译脚本中的venv是一个问题:没有venv,脚本可以在系统的其他地方工作(也就是说,python3 -c 'from Crypto.Cipher import AES'
不会失败)。在
否则,该过程运行良好:
(sometest) $ echo 'print("hello world")' > hello2.py
(sometest) $ cython -3 --embed hello2.py
(sometest) $ gcc -Os -I /usr/include/python3.5m -o hello2 hello2.c -lpython3.5m -lpthread -lm -lutil -ldl
(sometest) $ ./hello2
hello world
系统:
(sometest) $ python3 --version
Python 3.5.2
(sometest) $ pip3 freeze
Cython==0.29.11
pkg-resources==0.0.0
pycrypto==2.6.1
(sometest) $ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=16.04
DISTRIB_CODENAME=xenial
DISTRIB_DESCRIPTION="Ubuntu 16.04.6 LTS"
通常,Python解释器不是“独立”的,为了工作它需要它的标准库(例如}(已解释))和其他站点包的路径(例如
ctypes
(编译)或{numpy
)必须设置。在尽管通过冻结py模块并将所有c扩展(例如参见this SO-post)合并到生成的可执行文件中,使Python interpeter完全独立是可能的,但是为嵌入的interpeter提供所需的安装更容易。在
有时找到标准模块/站点包并不是开箱即用的:必须通过设置Python路径来帮助解释器,即通过在pyx文件中编程或通过在启动之前设置
<..>/sometest/lib/python3.5/site-packages
(sometest
是一个虚拟环境根文件夹)添加到sys.path
中。在请继续阅读,了解更多血腥的细节和其他解决方案。在
这个答案适用于Linux和Python3(Python3.7),Windows/MacOS的基本思想是相同的,但有些细节可能会有所不同。在
由于使用了
venv
,我们有以下备选方案来解决该问题:<..>/sometest/lib/python3.5/site-packages
(sometest
是一个虚拟环境根文件夹)添加到sys.path
中,可以在pyx文件中编程,也可以在启动之前设置PYTHONPATH
-环境变量。在sometest
的子目录中(例如bin
或创建自己的子目录)。在virtualenv
代替venv
。在注意:对于嵌入python的可执行文件,无论虚拟环境(或哪个)是否被激活,它都不起任何作用。在
为什么上面的方法可以解决您的场景中的问题?在
问题是,(嵌入式)Python解释器需要找出以下内容:
os.py
,argparse.py
(大多数都是*.py/*.pyc)。给定^{prefix/lib/pythonX.Y
)中。在exec_prefix/lib/pythonX.Y/lib-dynload
中找到)。在算法可以是found here,当执行^{} 时执行搜索。一旦找到这些目录,就可以构造
sys.path
。在但是,当使用
venv
时,有一个pyvenv.cfg
-filenext to exe or in the parent directory,它确保找到正确的Python Home—一个好的起点是该文件中的home
-键。在如果^{} 未设置,} (解释器可以找到它,因为
Py_Initialize
将利用^{sys.prefix
是已知的),或者更精确的是{a9},将虚拟环境的站点包添加到sys.path
。执行此操作时,site.py
将查找pyvenv.cfg
并对其进行解析。但是,本地site-packages
仅在以下情况下添加到python路径:在您的例子中,
pyvenv.cfg
不在上面的目录中,而是与exe在同一个目录中,因此不包括通过pip安装库的本地站点包。不包括全局站点包,因为pyvenv.cfg
具有键include-system-site-packages = false
。因此,不允许使用站点包,并且无法找到已安装的库。在但是,将exe向下移动一个目录,会导致将本地站点包包含到路径中。在
还有其他可能的情况,重要的是可执行文件的位置,而不是激活了哪个环境。在
A:可执行文件在某个地方,但不在虚拟环境中
对于已安装的python解释器,这种搜索启发式方法或多或少是可靠的,但也适用于嵌入式解释器或虚拟环境(有关更多信息,请参见this issue)。在
如果python是使用通常的
apt install
或类似的方式安装的,那么它将被找到(由于搜索算法中的4. step),并且系统安装将由嵌入式解释器使用。在但是,如果文件被移动,或者python是从源代码构建但未安装,则嵌入的interperter无法启动:
在这种情况下,^{} 或设置环境变量
$PYTHONHOME
是可能的解决方案。在B:在虚拟环境中可执行,使用virtualenv创建
假设虚拟环境和嵌入式Python的Python版本相同(否则我们有上述情况),emebeded exe将使用本地端包。由于this rule,主页搜索算法将始终找到本地主页:
在本例中,
argv0_path
是exe的路径(没有pyvenv.cfg
文件!),以及"landmarks"(lib/python$版本/操作系统py和lib/python$VERSION/lib dynload),因为它们在exe上面的本地home中以符号链接的形式出现。在C:可执行的两个文件夹,位于
venv
-环境的深处在
venv
-环境中查找两个而不是一个文件夹(它的工作位置)会导致在搜索home时无法读取pyvenv.cfg
文件(上面的位置太远),“venv”--环境缺少指向“landmarkers”的符号链接(只存在本地的侧包),这样的第3步将失败,4. step是唯一的希望。在推论:如果没有正确的Python安装,嵌入式Python将无法工作,除非:
所需的文件被打包到嵌入可执行文件旁边的}来扰乱搜索)。
lib\pythonX.Y\*
中,或者在上面的某个地方(并且没有{或者
pyvenv.cfg
用于将解释器指向正确的位置。相关问题 更多 >
编程相关推荐