标签归档:shared-libraries

为什么Python无法找到sys.path目录中的共享对象?

问题:为什么Python无法找到sys.path目录中的共享对象?

我正在尝试导入pycurl

$ python -c "import pycurl"
Traceback (most recent call last):
File "<string>", line 1, in <module>
ImportError: libcurl.so.4: cannot open shared object file: No such file or directory

现在,libcurl.so.4在中/usr/local/lib。如您所见,这是在sys.path

$ python -c "import sys; print(sys.path)"
['', '/usr/local/lib/python2.5/site-packages/setuptools-0.6c9-py2.5.egg', 
'/usr/local/lib/python25.zip', '/usr/local/lib/python2.5', 
'/usr/local/lib/python2.5/plat-linux2', '/usr/local/lib/python2.5/lib-tk', 
'/usr/local/lib/python2.5/lib-dynload', 
'/usr/local/lib/python2.5/sitepackages', '/usr/local/lib', 
'/usr/local/lib/python2.5/site-packages']

任何帮助将不胜感激。

I’m trying to import pycurl:

$ python -c "import pycurl"
Traceback (most recent call last):
File "<string>", line 1, in <module>
ImportError: libcurl.so.4: cannot open shared object file: No such file or directory

Now, libcurl.so.4 is in /usr/local/lib. As you can see, this is in sys.path:

$ python -c "import sys; print(sys.path)"
['', '/usr/local/lib/python2.5/site-packages/setuptools-0.6c9-py2.5.egg', 
'/usr/local/lib/python25.zip', '/usr/local/lib/python2.5', 
'/usr/local/lib/python2.5/plat-linux2', '/usr/local/lib/python2.5/lib-tk', 
'/usr/local/lib/python2.5/lib-dynload', 
'/usr/local/lib/python2.5/sitepackages', '/usr/local/lib', 
'/usr/local/lib/python2.5/site-packages']

Any help will be greatly appreciated.


回答 0

sys.path仅搜索Python模块。对于动态链接库,搜索的路径必须位于中LD_LIBRARY_PATH。检查您是否LD_LIBRARY_PATH包含了/usr/local/lib,如果没有,请添加并重试。

一些更多信息(来源):

在Linux中,环境变量LD_LIBRARY_PATH是用冒号分隔的目录集,在其中应首先搜索库,然后再搜索标准目录集;这在调试新库或出于特殊目的使用非标准库时很有用。环境变量LD_PRELOAD列出了具有覆盖标准集的功能的共享库,就像/etc/ld.so.preload一样。这些由加载程序/lib/ld-linux.so实现。我应该指出,虽然LD_LIBRARY_PATH在许多类Unix系统上都可以使用,但它并不是在所有系统上都可以使用。例如,此功能在HP-UX上可用,但作为环境变量SHLIB_PATH,在AIX上是通过变量LIBPATH(使用相同的语法,用冒号分隔的列表)来提供的。

更新:要设置LD_LIBRARY_PATH,最好在您的~/.bashrc 文件或等效文件中使用以下之一:

export LD_LIBRARY_PATH=/usr/local/lib

要么

export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH

如果第一种形式为空(等于空字符串,或者根本不存在),则使用第二种形式,如果不是,则使用第二种形式。注意使用导出

sys.path is only searched for Python modules. For dynamic linked libraries, the paths searched must be in LD_LIBRARY_PATH. Check if your LD_LIBRARY_PATH includes /usr/local/lib, and if it doesn’t, add it and try again.

Some more information (source):

In Linux, the environment variable LD_LIBRARY_PATH is a colon-separated set of directories where libraries should be searched for first, before the standard set of directories; this is useful when debugging a new library or using a nonstandard library for special purposes. The environment variable LD_PRELOAD lists shared libraries with functions that override the standard set, just as /etc/ld.so.preload does. These are implemented by the loader /lib/ld-linux.so. I should note that, while LD_LIBRARY_PATH works on many Unix-like systems, it doesn’t work on all; for example, this functionality is available on HP-UX but as the environment variable SHLIB_PATH, and on AIX this functionality is through the variable LIBPATH (with the same syntax, a colon-separated list).

Update: to set LD_LIBRARY_PATH, use one of the following, ideally in your ~/.bashrc or equivalent file:

export LD_LIBRARY_PATH=/usr/local/lib

or

export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH

Use the first form if it’s empty (equivalent to the empty string, or not present at all), and the second form if it isn’t. Note the use of export.


回答 1

确保您的libcurl.so模块位于系统库路径中,该路径与python库路径不同且独立。

“快速修复”是将此路径添加到LD_LIBRARY_PATH变量。但是,设置整个系统(甚至帐户范围)是一个糟糕的想法,因为可以通过某种方式设置它,以使某些程序会找到它不应该或者甚至更不希望打开安全漏洞的库。

如果您的“本地安装的库”安装在例如/ usr / local / lib中,请将此目录添加到/etc/ld.so.conf(这是一个文本文件),然后运行“ ldconfig”

该命令将运行缓存实用程序,但还将创建加载程序系统运行所需的所有必要“符号链接”。令人惊讶的是,libcurl的“ make install”尚未执行此操作,但如果/ usr / local / lib不在/etc/ld.so.conf中,则可能无法执行此操作。

PS:您的/etc/ld.so.conf可能只包含“ include ld.so.conf.d / *。conf”而不包含任何内容。您仍然可以在其后添加目录路径,或者只是在包含该目录的目录中创建一个新文件。不要忘记在它之后运行“ ldconfig”。

小心。弄错了会损坏您的系统。

另外:确保您的Python模块针对该版本的libcurl进行编译。如果您只是从其他系统复制了一些文件,则此方法将永远无法正常工作。如有疑问,请在要运行它们的系统上编译模块。

Ensure your libcurl.so module is in the system library path, which is distinct and separate from the python library path.

A “quick fix” is to add this path to a LD_LIBRARY_PATH variable. However, setting that system wide (or even account wide) is a BAD IDEA, as it is possible to set it in such a way that some programs will find a library it shouldn’t, or even worse, open up security holes.

If your “locally installed libraries” are installed in, for example, /usr/local/lib, add this directory to /etc/ld.so.conf (it’s a text file) and run “ldconfig”

The command will run a caching utility, but will also create all the necessary “symbolic links” required for the loader system to function. It is surprising that the “make install” for libcurl did not do this already, but it’s possible it could not if /usr/local/lib is not in /etc/ld.so.conf already.

PS: it’s possible that your /etc/ld.so.conf contains nothing but “include ld.so.conf.d/*.conf”. You can still add a directory path after it, or just create a new file inside the directory it’s being included from. Dont forget to run “ldconfig” after it.

Be careful. Getting this wrong can screw up your system.

Additionally: make sure your python module is compiled against THAT version of libcurl. If you just copied some files over from another system, this wont always work. If in doubt, compile your modules on the system you intend to run them on.


回答 2

最初编译pycurl时,还可以在用户环境中将LD_RUN_PATH设置为/ usr / local / lib。这会将/ usr / local / lib嵌入C扩展模块。的RPATH属性中,以便它在运行时自动知道在哪里可以找到该库,而不必在运行时设置LD_LIBRARY_PATH。

You can also set LD_RUN_PATH to /usr/local/lib in your user environment when you compile pycurl in the first place. This will embed /usr/local/lib in the RPATH attribute of the C extension module .so so that it automatically knows where to find the library at run time without having to have LD_LIBRARY_PATH set at run time.


回答 3

有完全相同的问题。我将curl 7.19安装到/ opt / curl /中,以确保不会影响生产服务器上的当前curl。将libcurl.so.4链接到/ usr / lib之后:

须藤ln -s /opt/curl/lib/libcurl.so /usr/lib/libcurl.so.4

我仍然遇到相同的错误!杜尔夫

但是运行ldconfig可以使链接变得很有效。完全不需要设置LD_RUN_PATH或LD_LIBRARY_PATH。只需运行ldconfig。

Had the exact same issue. I installed curl 7.19 to /opt/curl/ to make sure that I would not affect current curl on our production servers. Once I linked libcurl.so.4 to /usr/lib:

sudo ln -s /opt/curl/lib/libcurl.so /usr/lib/libcurl.so.4

I still got the same error! Durf.

But running ldconfig make the linkage for me and that worked. No need to set the LD_RUN_PATH or LD_LIBRARY_PATH at all. Just needed to run ldconfig.


回答 4

作为上述答案的补充-我只是遇到了类似的问题,并且完全使用默认安装的python进行工作。

当我调用要使用的共享库的示例时LD_LIBRARY_PATH,会得到如下信息:

$ LD_LIBRARY_PATH=/path/to/mysodir:$LD_LIBRARY_PATH python example-so-user.py
python: can't open file 'example-so-user.py': [Errno 2] No such file or directory

值得注意的是,它甚至不抱怨导入-它抱怨源文件!

但是如果我使用LD_PRELOAD以下命令强制加载对象:

$ LD_PRELOAD=/path/to/mysodir/mypyobj.so python example-so-user.py
python: error while loading shared libraries: libtiff.so.5: cannot open shared object file: No such file or directory

…我立即收到一条更有意义的错误消息-有关缺少的依赖项!

只是以为我会在这里写下来-干杯!

As a supplement to above answers – I’m just bumping into a similar problem, and working completely of the default installed python.

When I call the example of the shared object library I’m looking for with LD_LIBRARY_PATH, I get something like this:

$ LD_LIBRARY_PATH=/path/to/mysodir:$LD_LIBRARY_PATH python example-so-user.py
python: can't open file 'example-so-user.py': [Errno 2] No such file or directory

Notably, it doesn’t even complain about the import – it complains about the source file!

But if I force loading of the object using LD_PRELOAD:

$ LD_PRELOAD=/path/to/mysodir/mypyobj.so python example-so-user.py
python: error while loading shared libraries: libtiff.so.5: cannot open shared object file: No such file or directory

… I immediately get a more meaningful error message – about a missing dependency!

Just thought I’d jot this down here – cheers!


回答 5

我使用的python setup.py build_ext -R/usr/local/lib -I/usr/local/include/libcalg-1.0是已编译的.so文件,该文件位于build文件夹下。您可以键入python setup.py --help build_ext以查看-R和-I的解释

I use python setup.py build_ext -R/usr/local/lib -I/usr/local/include/libcalg-1.0 and the compiled .so file is under the build folder. you can type python setup.py --help build_ext to see the explanations of -R and -I


回答 6

对我来说,这里的工作是使用版本管理器,例如pyenv,我强烈建议您对项目环境和程序包版本进行良好的管理,并使其与操作系统的版本分开。

操作系统更新后,我也遇到了同样的错误,但是很容易用pyenv install 3.7-dev(我使用的版本)修复。

For me what works here is to using a version manager such as pyenv, which I strongly recommend to get your project environments and package versions well managed and separate from that of the operative system.

I had this same error after an OS update, but was easily fixed with pyenv install 3.7-dev (the version I use).


从Python中的相对路径导入

问题:从Python中的相对路径导入

我有一个用于客户代码的文件夹,一个用于我的服务器代码的文件夹,以及一个在他们之间共享的代码的文件夹

Proj/
    Client/
        Client.py
    Server/
        Server.py
    Common/
        __init__.py
        Common.py

如何从Server.py和Client.py导入Common.py?

I have a folder for my client code, a folder for my server code, and a folder for code that is shared between them

Proj/
    Client/
        Client.py
    Server/
        Server.py
    Common/
        __init__.py
        Common.py

How do I import Common.py from Server.py and Client.py?


回答 0

编辑2014年11月(3年后):

Python 2.6和3.x支持适当的相对导入,在这里您可以避免做任何棘手的事情。使用这种方法,您知道您得到的是相对导入而不是绝对导入。“ ..”表示转到我上方的目录:

from ..Common import Common

请注意,仅当您从包外部将python作为模块运行时,此方法才有效。例如:

python -m Proj

原始的骇客方式

在某些情况下,实际上您从来没有“安装”软件包,这种方法仍然很常用。例如,它在Django用户中很流行。

您可以将Common /添加到您的sys.path中(python用来导入内容的路径列表):

import sys, os
sys.path.append(os.path.join(os.path.dirname(__file__), '..', 'Common'))
import Common

os.path.dirname(__file__) 只需为您提供当前python文件所在的目录,然后我们导航至该目录的“ Common /”并导入“ Common”模块。

EDIT Nov 2014 (3 years later):

Python 2.6 and 3.x supports proper relative imports, where you can avoid doing anything hacky. With this method, you know you are getting a relative import rather than an absolute import. The ‘..’ means, go to the directory above me:

from ..Common import Common

As a caveat, this will only work if you run your python as a module, from outside of the package. For example:

python -m Proj

Original hacky way

This method is still commonly used in some situations, where you aren’t actually ever ‘installing’ your package. For example, it’s popular with Django users.

You can add Common/ to your sys.path (the list of paths python looks at to import things):

import sys, os
sys.path.append(os.path.join(os.path.dirname(__file__), '..', 'Common'))
import Common

os.path.dirname(__file__) just gives you the directory that your current python file is in, and then we navigate to ‘Common/’ the directory and import ‘Common’ the module.


回答 1

有趣的是,我刚刚遇到了一个相同的问题,我可以通过以下方式获得这项工作:

结合linux命令ln,我们可以使事情变得更加简单:

1. cd Proj/Client
2. ln -s ../Common ./

3. cd Proj/Server
4. ln -s ../Common ./

而且,现在,如果some_stuff要从file:Proj/Common/Common.py导入到file:中Proj/Client/Client.py,就像这样:

# in Proj/Client/Client.py
from Common.Common import some_stuff

并且,同样适用于Proj/Server,也适用于setup.py过程, 此处讨论的相同问题,希望对您有所帮助!

Funny enough, a same problem I just met, and I get this work in following way:

combining with linux command ln , we can make thing a lot simper:

1. cd Proj/Client
2. ln -s ../Common ./

3. cd Proj/Server
4. ln -s ../Common ./

And, now if you want to import some_stuff from file: Proj/Common/Common.py into your file: Proj/Client/Client.py, just like this:

# in Proj/Client/Client.py
from Common.Common import some_stuff

And, the same applies to Proj/Server, Also works for setup.py process, a same question discussed here, hope it helps !


回答 2

不要做相对导入。

PEP8

强烈建议不要将相对进口用于包装内进口。

将所有代码放入一个超级包(即“ myapp”)中,并将子包用于客户端,服务器和通用代码。

更新:Python 2.6和3.x支持正确的相对导入(…) ”。有关更多详细信息,请参见Dave的答案

Don’t do relative import.

From PEP8:

Relative imports for intra-package imports are highly discouraged.

Put all your code into one super package (i.e. “myapp”) and use subpackages for client, server and common code.

Update:Python 2.6 and 3.x supports proper relative imports (…)“. See Dave’s answers for more details.


回答 3

进行相对导入绝对可以!这是我的小事:

#first change the cwd to the script path
scriptPath = os.path.realpath(os.path.dirname(sys.argv[0]))
os.chdir(scriptPath)

#append the relative location you want to import from
sys.path.append("../common")

#import your module stored in '../common'
import common.py

Doing a relative import is absolulutely OK! Here’s what little ‘ol me does:

#first change the cwd to the script path
scriptPath = os.path.realpath(os.path.dirname(sys.argv[0]))
os.chdir(scriptPath)

#append the relative location you want to import from
sys.path.append("../common")

#import your module stored in '../common'
import common.py

回答 4

从PYTHONPATH开始,默认的导入方法已经是“相对的”。默认情况下,PYTHONPATH是某些系统库以及原始源文件的文件夹。如果使用-m运行以运行模块,则当前目录将添加到PYTHONPATH中。因此,如果程序的入口点位于Proj内,则import Common.Common在Server.py和Client.py内都可以使用。

不要做相对导入。它不会按您希望的那样工作。

The default import method is already “relative”, from the PYTHONPATH. The PYTHONPATH is by default, to some system libraries along with the folder of the original source file. If you run with -m to run a module, the current directory gets added to the PYTHONPATH. So if the entry point of your program is inside of Proj, then using import Common.Common should work inside both Server.py and Client.py.

Don’t do a relative import. It won’t work how you want it to.