使 distutils 将编译后的扩展放在正确的文件夹中
Make distutils place compiled extensions in the right folder
我用 distutils 编写了一个 Python C 扩展。这是 setup.py
:
from distutils.core import setup, Extension
utilsmodule = Extension('utils', sources = ['utilsmodule.c'])
setup (name = 'myPackage',
version = '1.0',
description = 'My package',
ext_modules = [utilsmodule])
当我 运行 python setup.y build
时,扩展构建正确,但 .pyd
文件进入文件夹 build/lib.win-amd64-3.7
,而不是模块的根 Python 查找要导入的模块。我需要在构建后将该文件移出 build
才能导入它。
我想在 setup()
之后添加一行来移动文件,但这似乎有点脏,我猜 distutils 应该可以完成这项工作。
编译扩展的正确方法是什么可以在构建后立即被其他 Python 文件导入?
distutils should do that work.
不应该。构建只是打包、安装和使用的中间阶段。
What is the right way to compile an extension in a way that it can be imported by other Python files immediately after build?
没有这种方法。您可以将 %PYTHONPATH%
设置为指向 build/lib.win-amd64-3.7
并直接从 build/
.
导入模块
或者您可以尝试改变 distutils:
from distutils.core import setup
from distutils.command.build_ext import build_ext as _build_ext
import os
class build_ext(_build_ext):
def run(self):
_build_ext.run(self)
os.rename("build/lib.win-amd64-3.7/%s" % mypydname, dest_dir)
setup(
…
cmdclass={'build_ext': build_ext},
…
)
但是无论如何您都必须决定将编译后的模块移动到哪里。
2022年更新资料~
如果你想在你开发包的项目中测试你的模块,我认为更改扩展名然后使用 --inplace
标志就足够了。
例如,如果 this_package
是您的扩展名,并且您希望您的包结构如下:
project_dir
|-- package
| |-- __init__.py
| |-- this_package.xxxx.so
| |-- other.py
|-- setup.py
您可以像这样设置此扩展程序的名称:
Extension("package.this_package", source_files)
然后通过以下方式构建它:
python setup.py build_ext --inplace
如果你想分发和发布包,并且你希望安装包的结构也像上面那样。
如果您愿意共享您的源文件,您可以使用 python setup.py sdist
创建 .tar.gz
发行版。如果所有的源文件都集中在.tar.gz
文件中(通过配置setup.py
)。该软件包将在目标机器上正确构建,然后安装在具有这种结构的 site-packages
目录中。
如果没有,您可能需要使用 python setup.py bdist_wheel
或其他东西来构建用于发布的二进制轮。它会在本地构建库,并且(我认为)我们只能发布 .so
库。但是,.whl
依赖于 OS+Arch,因此您可能需要为不同的 OS+Arch.
构建多个发行版
无论我们使用什么方式,通过为扩展名设置名称 package.this_package
,您总是可以在适当的位置使用 .so
。
我用 distutils 编写了一个 Python C 扩展。这是 setup.py
:
from distutils.core import setup, Extension
utilsmodule = Extension('utils', sources = ['utilsmodule.c'])
setup (name = 'myPackage',
version = '1.0',
description = 'My package',
ext_modules = [utilsmodule])
当我 运行 python setup.y build
时,扩展构建正确,但 .pyd
文件进入文件夹 build/lib.win-amd64-3.7
,而不是模块的根 Python 查找要导入的模块。我需要在构建后将该文件移出 build
才能导入它。
我想在 setup()
之后添加一行来移动文件,但这似乎有点脏,我猜 distutils 应该可以完成这项工作。
编译扩展的正确方法是什么可以在构建后立即被其他 Python 文件导入?
distutils should do that work.
不应该。构建只是打包、安装和使用的中间阶段。
What is the right way to compile an extension in a way that it can be imported by other Python files immediately after build?
没有这种方法。您可以将 %PYTHONPATH%
设置为指向 build/lib.win-amd64-3.7
并直接从 build/
.
或者您可以尝试改变 distutils:
from distutils.core import setup
from distutils.command.build_ext import build_ext as _build_ext
import os
class build_ext(_build_ext):
def run(self):
_build_ext.run(self)
os.rename("build/lib.win-amd64-3.7/%s" % mypydname, dest_dir)
setup(
…
cmdclass={'build_ext': build_ext},
…
)
但是无论如何您都必须决定将编译后的模块移动到哪里。
2022年更新资料~
如果你想在你开发包的项目中测试你的模块,我认为更改扩展名然后使用 --inplace
标志就足够了。
例如,如果 this_package
是您的扩展名,并且您希望您的包结构如下:
project_dir
|-- package
| |-- __init__.py
| |-- this_package.xxxx.so
| |-- other.py
|-- setup.py
您可以像这样设置此扩展程序的名称:
Extension("package.this_package", source_files)
然后通过以下方式构建它:
python setup.py build_ext --inplace
如果你想分发和发布包,并且你希望安装包的结构也像上面那样。
如果您愿意共享您的源文件,您可以使用
python setup.py sdist
创建.tar.gz
发行版。如果所有的源文件都集中在.tar.gz
文件中(通过配置setup.py
)。该软件包将在目标机器上正确构建,然后安装在具有这种结构的site-packages
目录中。如果没有,您可能需要使用
构建多个发行版python setup.py bdist_wheel
或其他东西来构建用于发布的二进制轮。它会在本地构建库,并且(我认为)我们只能发布.so
库。但是,.whl
依赖于 OS+Arch,因此您可能需要为不同的 OS+Arch.
无论我们使用什么方式,通过为扩展名设置名称 package.this_package
,您总是可以在适当的位置使用 .so
。