Python无法找到外部依赖dll

2024-09-27 00:12:57 发布

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

我正在使用Python3.6。我已经用(PybDun11)创建了一个C++扩展名。https://github.com/pybind/pybind11]. 我将编译的*.pyd文件以及依赖的dll复制到站点包中。但是当我试图从外部DLL加载任何函数时,python抱怨函数不存在。如果我想访问函数,我需要写

sys.path.append(r'C:\Users\test\AppData\Local\Programs\Python\Python36\Lib\site-packages\CppProject')

或者我需要向PYTHONPATH环境变量添加相同的路径

为什么Python不能加载函数,即使它与pyd位于同一路径中?我不想每次需要使用模块或环境变量时都附加sys路径?有没有办法避免这种情况?是否有任何方法可以在用户导入模块时自动将此路径添加到sys

enter image description here

例如:

CppExport.dll

#ifdef CPPEXPORT_EXPORTS
#define CPPEXPORT_API __declspec(dllexport)
#else
#define CPPEXPORT_API __declspec(dllimport)
#endif

extern "C" CPPEXPORT_API double sin_impl(double x);


const double e = 2.7182818284590452353602874713527;
double sin_impl(double x){
    return (1 - pow(e, (-2 * x))) / (2 * pow(e, -x));
}

cpproject.pyd

PYBIND11_MODULE(CppProject, m) {

    m.def("sin_impl", &sin_impl, R"pbdoc(
        Compute a hyperbolic tangent of a single argument expressed in radians.
    )pbdoc");

#ifdef VERSION_INFO
    m.attr("__version__") = VERSION_INFO;
#else
    m.attr("__version__") = "dev";
#endif
}

Setup.py

from setuptools import setup
import distutils
import sys

from setuptools.dist import Distribution

from distutils.sysconfig import get_python_lib
relative_site_packages = get_python_lib().split(sys.prefix+os.sep)[1]
date_files_relative_path = os.path.join(relative_site_packages, "CppProject")

class BinaryDistribution(Distribution):
    """Distribution which always forces a binary package with platform name"""
    def has_ext_modules(foo):
        return True


setup(
    name='CppProject',
    version='1.0',
    description='CppProject Library',
    packages=['CppProject'],
    package_data={
        'CppProject': ['CppProject.pyd'],
    },
    data_files = [(date_files_relative_path, ["CppExport.dll"])],
    distclass=BinaryDistribution
)

在Python中:

from CppProject import sin_impl

错误:

ImportError: cannot import name 'sin_impl'

完整代码出现在Github


Tags: path函数fromimport路径packagessyssin
2条回答

当您显式地将目录添加到sys.path时,代码可以工作,这一事实是理解发生了什么的关键

由于site-packages是解释器在导入模块时搜索的位置之一,因此此语句:

from CppProject import sin_impl

实际上正在CppProject文件夹中搜索名为sin_impl的模块

相反,你应该:

from CppProject.CppProject import sin_impl

它指向同名的实际模块

实际上,这并不需要在CppProject内部存在__init__.py来将其限定为Python包,因为Python 3.3+实现了隐式命名空间包

但是,当您构建具有许多依赖项的复杂程序时,包构造函数允许您在执行任何常规模块之前添加某种要执行的初始化

对不起,前面的回复,这里有一些更好的建议:

要分发库,需要创建setup.py和init.py。完成此操作后,您将能够使用python setup.py install安装软件包

对于我来说,setup.py看起来像:

README_rst = ''
from distutils.core import setup
with open('README.rst', mode='r', encoding='utf-8') as fd:
    README_rst = fd.read()

setup(
    name='MyStack',
    version='0.0.1',
    description='Cool short description',
    author='Author',
    author_email='author@mail.com',
    url='repo.com',
    packages=['Pkg'],
    long_description=README_rst,
    include_package_data=True,
    classifiers=[
        # Trove classifiers
        # The full list is here: https://pypi.python.org/pypi?%3Aaction=list_classifiers
        'Development Status :: 3 - Alpha',
    ]
)

init.py中,您必须找到您的库并导入它。以下是Qt的一个示例:

def find_qt():
    import os

    path = os.environ['PATH']

    dll_dir = os.path.dirname(__file__) + '\\Qt\\bin'
    if os.path.isfile(dll_dir + '\\Qt5Core.dll'):
        path = dll_dir + ';' + path
        os.environ['PATH'] = path
    else:
        for dll_dir in path.split(';'):
            if os.path.isfile(dll_dir + '\\Qt5Core.dll'):
                break
        else:
            raise ImportError("unable to find Qt5Core.dll on PATH")

    try:
        os.add_dll_directory(dll_dir)
    except AttributeError:
        pass


find_qt()
del find_qt

希望这有帮助

相关问题 更多 >

    热门问题