【问题标题】:Rust libraries made with PyO3 and rust-cpython won't import when running pytest使用 PyO3 和 rust-cpython 制作的 Rust 库在运行 pytest 时不会导入
【发布时间】:2021-08-10 15:35:17
【问题描述】:

在遵循有关编译 Rust 库以进一步从 Python 导入的各种教程(我已经尝试过 PyO3rust-cpython)时,我已经能够构建一个简单的库并成功地从我的 main.py 导入它和交互式 Python shell。

但是,在尝试测试纯 Python 和我的 Rust 库并进行基准测试时,我总是遇到导入错误:

_____________________________________________ ERROR collecting main.py _____________________________________________
ImportError while importing test module '/Users/xxx/pyo3/sumlib/main.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
/Users/xxx/.pyenv/versions/3.8.2/lib/python3.8/importlib/__init__.py:127: in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
main.py:1: in <module>
    import sumlib
E   ModuleNotFoundError: No module named 'sumlib'

同样,该库可以很好地从主 python 文件和交互式 shell(如 IPython)导入。

我在 macOS Big Sur 上,使用pyenv 安装了 Python 3.8。这是我的Cargo.toml

[package]
name = "sumlib"
version = "0.1.0"
edition = "2018"

[lib]
name = "sumlib"
# "cdylib" is necessary to produce a shared library for Python to import from.
#
# Downstream Rust code (including code in `bin/`, `examples/`, and `tests/`) will not be able
# to `use string_sum;` unless the "rlib" or "lib" crate type is also included, e.g.:
# crate-type = ["cdylib", "rlib"]
crate-type = ["cdylib", "rlib"]

[dependencies.pyo3]
version = "0.14.2"
features = ["extension-module"]

PyO3rust-cpython 到相同的结果,其他一切都非常简单。

【问题讨论】:

  • 你是如何打包你的模块的? PyO3 文档中有 a section on packaging tools
  • 我基本上是按照说明操作的,比如我用了maturin+PyO3的虚拟环境,它生成并安装了有效的轮子,但它似乎仍然无法导入我编译的动态库特别来自pytest

标签: python rust pytest pyo3


【解决方案1】:

tl/dr:使用 python -m pytest 而不是 pytest 调用您的测试。


听起来您还没有安装 Python 扩展模块(例如,使用 pip install),而是依赖于它位于您的工作目录中。这将允许您使用解释器或通过python -m 启动的main.py 导入它,

$ tree .
.
├── bin
│   ├── __init__.py
│   └── sumlib.py
└── examples
    └── main.py

2 directories, 3 files
$ ipython --no-banner

In [1]: from bin import sumlib

In [2]: exit()

$ python -m examples.main
Successfully imported sumlib!

但不使用pytest examples/main.pypython examples/main.py

$ pytest examples/main.py
======================================================= test session starts =======================================================
platform darwin -- Python 3.8.3, pytest-6.2.4, py-1.10.0, pluggy-0.13.1
rootdir: ...
plugins: typeguard-2.10.0
collected 0 items / 1 error

============================================================= ERRORS ==============================================================
________________________________________________ ERROR collecting examples/main.py ________________________________________________
ImportError while importing test module '.../examples/main.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
.../python3.8/importlib/__init__.py:127: in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
examples/main.py:5: in <module>
    from bin import sumlib
E   ModuleNotFoundError: No module named 'bin'
...
$ python examples/main.py
Traceback (most recent call last):
  File "examples/main.py", line 5, in <module>
    from bin import sumlib
ModuleNotFoundError: No module named 'bin'

这是因为ipythonpython -m 都将包含您的扩展模块的当前目录添加到Python 的sys.path,但pytest examples/main.pypython examples/main.py 没有。 (请参阅pytest docs。)您可以通过安装扩展模块或使用python -m pytest 而不是pytest 运行测试来解决此问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-06-06
    • 2021-01-25
    • 2022-11-26
    • 1970-01-01
    • 2022-11-09
    • 1970-01-01
    • 2022-12-04
    • 1970-01-01
    相关资源
    最近更新 更多