当前位置: 首页 > 面试题库 >

如何处理Linux / Python依赖项?

鄢子平
2023-03-14
问题内容

由于缺乏对我想使用的某些库的支持,我将一些Python开发从Windows迁移到Linux开发。我整天的大部分时间都在搞弄依赖关系无所适从。

问题

每当我选择Linux时,无论是通过apt-get,easy_install还是pip进行安装,我通常都会遇到某种依赖问题,通常与开发库有关。我本可以将几天的时间浪费在应该是简单的任务上,而不是编写代码,而要花更长的时间使库工作。
在哪里可以了解解决此类问题的策略,而不是漫无目的地搜索曾经遇到过相同问题的人?

一个例子

仅举一个例子:我想生成一些QR码。所以,我想我会用github.com/bitly/pyqrencode这是基于pyqrcode.sourceforge.net但据说没有Java的依赖关系。还有其他(pyqrnative,github.com/

Arachnid
/ pyqrencode),但是这似乎是满足我需求的最佳选择。

因此,我在pypi上找到了该软件包,并认为使用它会使生活更轻松:

(通过使用virtualenv使事情保持整洁,我可能使自己的生活更加困难。)

(myenv3)mat@ubuntu:~/myenv3$ bin/pip install pyqrencode
Downloading/unpacking pyqrencode
  Downloading pyqrencode-0.2.tar.gz
  Running setup.py egg_info for package pyqrencode

Installing collected packages: pyqrencode
  Running setup.py install for pyqrencode
    building 'qrencode' extension
    gcc -pthread -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -fPIC -I/usr/include/python2.7 -c qrencode.c -o build/temp.linux-i686-2.7/qrencode.o
    gcc -pthread -shared -Wl,-O1 -Wl,-Bsymbolic-functions -Wl,-Bsymbolic-functions build/temp.linux-i686-2.7/qrencode.o -lqrencode -o build/lib.linux-i686-2.7/qrencode.so

Successfully installed pyqrencode
Cleaning up...

(我想我可能sudo apt-get install libqrencode-dev也在那之前的某个时候。)

因此,我尝试运行测试脚本:

(myenv3)mat@ubuntu:~/myenv3$ python test_qr.py 
Traceback (most recent call last):
  File "test_qr.py", line 1, in <module>
    from qrencode import Encoder
  File "qrencode.pyx", line 1, in init qrencode (qrencode.c:1520)
ImportError: No module named ImageOps

:(

好吧,调查发现ImageOps似乎是PIL的一部分…

(myenv3)mat@ubuntu:~/myenv3$ pip install pil
Downloading/unpacking pil
  Downloading PIL-1.1.7.tar.gz (506Kb): 122Kb downloaded
Operation cancelled by user
Storing complete log in /home/mat/.pip/pip.log
(myenv3)mat@ubuntu:~/myenv3$ bin/pip install pil
Downloading/unpacking pil
  Downloading PIL-1.1.7.tar.gz (506Kb): 506Kb downloaded
  Running setup.py egg_info for package pil
    WARNING: '' not a valid package name; please use only.-separated package names in setup.py

Installing collected packages: pil
  Running setup.py install for pil
    WARNING: '' not a valid package name; please use only.-separated package names in setup.py
    building '_imaging' extension
    gcc ...
    building '_imagingmath' extension
    gcc ...
    --------------------------------------------------------------------
    PIL 1.1.7 SETUP SUMMARY
    --------------------------------------------------------------------
    version       1.1.7
    platform      linux2 2.7.1+ (r271:86832, Apr 11 2011, 18:05:24)
                  [GCC 4.5.2]
    --------------------------------------------------------------------
    *** TKINTER support not available
    *** JPEG support not available
    *** ZLIB (PNG/ZIP) support not available
    *** FREETYPE2 support not available
    *** LITTLECMS support not available
    --------------------------------------------------------------------
    To add a missing option, make sure you have the required
    library, and set the corresponding ROOT variable in the
    setup.py script.

    To check the build, run the selftest.py script.
    ...
Successfully installed pil
Cleaning up...

嗯,已经安装了PIL,但是还没有拿起我sudo apt-get install libjpeg62 libjpeg62-dev libpng12-dev zlib1g zlib1g-dev以前安装的库。我不确定如何告诉pip将库位置提供给setup.py。谷歌搜索提出了我尝试过的各种想法,但是除了让我转圈而论外,这些想法似乎无济于事。

Ubuntu11.04:建议使用PIP将PIL安装到virtualenv中,而不是使用pillow软件包,所以让我们尝试一下:

(myenv3)mat@ubuntu:~/myenv3$ pip install pillow
Downloading/unpacking pillow
  Downloading Pillow-1.7.5.zip (637Kb): 637Kb downloaded
  Running setup.py egg_info for package pillow

    ...
Installing collected packages: pillow
  Running setup.py install for pillow
    building '_imaging' extension
    gcc ...
    --------------------------------------------------------------------
    SETUP SUMMARY (Pillow 1.7.5 / PIL 1.1.7)
    --------------------------------------------------------------------
    version       1.7.5
    platform      linux2 2.7.1+ (r271:86832, Apr 11 2011, 18:05:24)
                  [GCC 4.5.2]
    --------------------------------------------------------------------
    *** TKINTER support not available
    --- JPEG support available
    --- ZLIB (PNG/ZIP) support available
    --- FREETYPE2 support available
    *** LITTLECMS support not available
    --------------------------------------------------------------------
    To add a missing option, make sure you have the required
    library, and set the corresponding ROOT variable in the
    setup.py script.

    To check the build, run the selftest.py script.
    ...
Successfully installed pillow
Cleaning up...

好吧,这次我们似乎已经支持JPEG和PNG了!

(myenv3)mat@ubuntu:~/myenv3$ python test_qr.py 
Traceback (most recent call last):
  File "test_qr.py", line 1, in <module>
    from qrencode import Encoder
  File "qrencode.pyx", line 1, in init qrencode (qrencode.c:1520)
ImportError: No module named ImageOps

仍然没有ImageOps。现在我很困惑,枕头上缺少ImageOps,还是pil也存在其他问题。


问题答案:

我在这里看到两个单独的问题:

  1. 跟踪项目所需的所有python模块。

  2. 跟踪项目中python模块所需的所有动态库。

对于第一个问题,我发现扩建是很好的帮助,尽管要花一点时间才能掌握。

在您的情况下,我将从为新项目创建目录开始。然后,我进入该目录并下载 bootstrap.py

wget http://python-distribute.org/bootstrap.py

然后,我将创建一个 buildout.cfg 文件:

[buildout]
parts = qrproject
        python
eggs = pyqrencode

[qrproject]
recipe = z3c.recipe.scripts
eggs = ${buildout:eggs}
entry-points= qrproject=qrprojectmodule:run
extra-paths = ${buildout:directory}

# This is a simple way of creating an interpreter that will have
# access to all the eggs / modules that this project uses.
[python]
recipe = z3c.recipe.scripts
interpreter = python
eggs = ${buildout:eggs}
extra-paths = ${buildout:directory}

在这种 buildout.cfg 我引用模块 qrprojectmodule (在 入口点[qrproject] 。这将创建一个斌/
qrproject运行该功能 运行 在模块 qrprojectmodule ,所以我也将创建文件 qrprojectmodule.py

import qrencode

def run():
    print "Entry point for qrproject. Happily imports qrencode module"

现在该使用您要使用的python二进制文件运行 bootstrap.py 了:

python bootstrap.py

然后运行生成的 bin / buildout

bin/buildout

这将在 bin / 目录中创建另外两个二进制文件 -bin / qrprojectbin / python
。前者是项目的主要二进制文件。每次您运行buildout时,它都会自动创建,并包含您要加载的所有模块和鸡蛋。第二个简单的方法是获得python提示符的简便方法,该提示符会在其中装载所有模块和鸡蛋,以便于调试。很好的是,bin
/ buildout将自动安装已将鸡蛋(在您的情况下为pyqrencode)指定为依赖项的所有python鸡蛋。

实际上,在运行 bin / buildout
的步骤中,您可能会遇到编译错误。这是因为您需要解决问题2:系统上所有可用的动态库。在Linux上,通常最好从包装系统中获取帮助。我要假设您在这里使用的是Debian衍生版本,例如Ubuntu。

pyqrencode网站指定您需要libqrencode库才能使pyqrencode正常工作。所以我用包管理器来搜索:

$ apt-cache search libqrencode
libqrencode-dev - QR Code encoding library -- development
libqrencode3 - QR Code encoding library
qrencode - QR Code encoder into PNG image

在这种情况下,我需要-dev软件包,因为它安装了编译python C模块所需的可链接库和头文件。另外,程序包管理器中的依赖系统将确保,如果我安装
libqrencode-dev ,我还将获得 libqrencode3 ,这是运行时(即在模块编译之后)所需的。

因此,我安装了软件包:

sudo apt-get install libqrencode-dev

完成后,重新运行bin / buildout,并且pyqrencode模块将(希望)编译并成功安装。现在尝试运行 bin / qrproject

$ bin/qrproject 
Entry point for qrproject. Happily imports qrencode module

成功!:-)

因此,总而言之:

  1. 使用buildout自动下载并安装项目所需的所有python模块/鸡蛋。

  2. 使用系统的软件包管理器来安装您使用的python模块所需的任何动态(C)库。

请注意,在很多情况下,软件包系统中已经提供了python模块的打包版本。例如,可以通过在Ubuntu上安装 python-imaging
软件包来获得pil 。在这种情况下,您不需要通过buildout进行安装,也不必担心库是否可用-
程序包管理器将安装模块运行所需的所有依赖项。但是,通过构建完成它可以使分发项目并使它在其他系统上运行更加容易。



 类似资料:
  • 我正在使用一个库,它提供了一个c可执行文件的python包装器。 我安装它(https://github.com/bulletphysics/bullet3)使用venv(https://docs.python.org/3/library/venv.html)-一切都很好。 我正在考虑尝试构建 https://github.com/bulletphysics/bullet3 从venv文件夹的根目

  • 在移动和PC的flutter应用程序上工作,移动插件通常涵盖iOS和android,因此移动的代码库保持不变。现在有了PC和Web,插件并不适用于所有平台。在dart.io有Platform.isIOS等可以根据平台更改行为,但仅限于运行时。例如,如果Windows上不存在插件,我需要在编译时有条件地导入插件。像相机、sqlite数据库、文件缓存等。有人说要让平台相关代码进入小部件等,但我仍然需要

  • a、b的变动都会调用ajax() 而且a变动的时候b也会发生变化,现在的问题是a变化的时候自己调用了一次ajax()并且引起了b变化,又触发了ajax()请问这种场景怎么处理?

  • 我有一个jar文件集合,其依赖关系为菱形模式:               /           \ Dep1.JAR ;     Dep2.JAR                         /                 我想用ProGuard对它们进行模糊处理,以保留它们的依赖关系,例如,这样base.jar和dep2.jar的模糊版本就可以单独执行,而不需要dep1.jar和de

  • 问题内容: 我最近一直在使用nodejs,并且仍然要处理模块系统,因此很抱歉这是一个明显的问题。我想要大致如下的代码: a.js (主文件与节点一起运行) b.js 我的问题似乎是我无法从ClassB实例中访问ClassA实例。 有没有正确/更好的方法来构造模块来实现我想要的?是否有更好的方式在模块之间共享变量? 问题答案: 尽管node.js确实允许循环依赖,但正如您所发现的那样,它可能很杂乱,

  • 我最近一直在使用nodejs,并且仍然在掌握模块系统,所以如果这是一个明显的问题,请原谅。我想要大致如下的代码: a.js(主文件与节点一起运行) b.js 我的问题似乎是我无法从ClassB的实例中访问ClassA的实例。 有没有正确/更好的方法来构建模块以实现我想要的?有没有更好的方法在模块之间共享变量?