如何将FreeCAD嵌入到Python虚拟环境中?

tom*_*mpi 6 debian virtualenv pycharm python-3.x freecad

如何设置嵌入了 FreeCAD 库的 Python 虚拟环境,以便能够作为模块导入到脚本中?

在使用使用 FreeCAD 库创建和修改 3D 几何图形的 Python 脚本时,我希望避免使用 FreeCAD GUI 以及依赖于系统上安装的 FreeCAD。我希望 Python 虚拟环境能让这一切成为可能。

我正在 Debian 10 上的 virtualenv 中使用 PyCharm 2021.1.1 和 Python 3.8 工作。

我开始使用嵌入脚本的 FreeCAD 文档作为基础:

https://wiki.freecadweb.org/Embedding_FreeCAD

在一次尝试中,我从 Debian 下载并解压了 .deb 软件包,并注意获取每个依赖项所需的正确版本。在另一次尝试中,我复制了 FreeCAD flatpak 安装的内容,因为它应该包含 FreeCAD 依赖的所有库。

将要导入的库放入虚拟机文件夹后,我通过各种尝试使用 sys.path.append() 以及 PyCharm 的项目结构工具来指向它们。在这两种情况下,虚拟环境都会检测 FreeCAD.so 所在的位置,但无法找到其任何依赖项,即使位于同一文件夹中也是如此。当显式导入这些依赖项时,它们每个都有相同的问题。当导入失败时,这会导致死胡同,因为它没有根据Python定义模块导出函数:

ImportError: dynamic module does not define module export function (PyInit_libnghttp2)
Run Code Online (Sandbox Code Playgroud)

尽管我提供了所需的库并告知 Python 它们的位置,但我似乎正在查看一条很长的破碎依赖链。

我希望能够获得有关如何执行此操作的直接说明或描述在 Python 虚拟环境中导入 FreeCAD 库的文档的指针,因为我还没有遇到任何特定的内容。

我之前遇到了一些似乎有类似意图的问题,但没有答案:

在 python 脚本中嵌入 FreeCAD

是否可以将 Blender/Freecad 嵌入到 python 程序中?

Conda 的类似问题侧重于从主机系统导入库,而不是将它们嵌入到虚拟环境中:

仅在一个 conda 虚拟环境的系统路径中包含 FreeCAD

FreeCAD 论坛上其他人的问题没有得到解答:

https://forum.freecadweb.org/viewtopic.php?t=27929

编辑:

弄清楚这一点是一次很棒的学习经历。将依赖项拼凑在一起的问题在于,要使该方法发挥作用,从 FreeCAD 及其依赖项到 Python 解释器及其依赖项的所有内容似乎都需要构建在它们所依赖的库的相同版本上,以避免造成分段使一切戛然而止的故障。这意味着从 Flatpak 安装中获取它所依赖的 FreeCAD 模块和库的想法理论上并不可怕,因为所有部分都是使用相同的库版本构建在一起的。我只是无法解决这个问题,大概是由于所包含的库的位置以及难以识别所包含的 Python 解释器的可执行文件。最后,我研究了 FreeCAD AppImage 的内容,结果发现文件夹结构中包含了所需的所有内容,该结构似乎非常符合 PyCharm 和 Python 对模块和库的期望。

tom*_*mpi 6

这就是我为让 FreeCAD 与 PyCharm 和 virtualenv 一起使用所做的事情:

下载 FreeCAD AppImage

https://www.freecadweb.org/downloads.php

使 AppImage 可执行

chmod -v +x ~/Downloads/FreeCAD_*.AppImage
Run Code Online (Sandbox Code Playgroud)

创建用于提取AppImage的文件夹

mkdir -v ~/Documents/freecad_appimage
Run Code Online (Sandbox Code Playgroud)

从文件夹中提取 AppImage(注意:这会扩展到接近 30000 个文件,需要超过 2 GB 磁盘空间)

cd ~/Documents/freecad_appimage

~/Downloads/./FreeCAD_*.AppImage --appimage-extract 
Run Code Online (Sandbox Code Playgroud)

为 PyCharm 项目创建文件夹

mkdir -v ~/Documents/pycharm_freecad_project
Run Code Online (Sandbox Code Playgroud)

使用Python解释器从提取的AppImage创建pycharm项目

Location: ~/Documents/pycharm_freecad_project
New environment using: Virtualenv
Location: ~/Documents/pycharm_freecad_project/venv
Base interpreter: ~/Documents/freecad_appimage/squashfs-root/usr/bin/python
Inherit global site-packages: False
Make available to all projects: False
Run Code Online (Sandbox Code Playgroud)

将包含 FreeCAD.so 库的文件夹添加为 PyCharm 项目结构的内容根并标记为源(通过这样做,您不必设置 PYTHONPATH 或 sys.path 值,因为 PyCharm 向解释器提供模块位置信息)

File: Settings: Project: Project Structure: Add Content Root
~/Documents/freecad_appimage/squashfs-root/usr/lib
Run Code Online (Sandbox Code Playgroud)

此后,PyCharm 会忙于索引文件一段时间。

在 PyCharm 中打开 Python 控制台并运行命令来检查基本功能

import FreeCAD
Run Code Online (Sandbox Code Playgroud)

创建具有示例功能的 python 脚本

import FreeCAD
vec = FreeCAD.Base.Vector(0, 0, 0)
print(vec)
Run Code Online (Sandbox Code Playgroud)

运行脚本

调试脚本

到目前为止,我在脚本中使用的所有 FreeCAD 功能都有效。然而,一个问题似乎是 FreeCAD 模块需要在 Path 模块之前导入。否则,Python 解释器将退出并显示代码 139(被信号 11:SIGSEGV 中断)。

PyCharm 有几个问题:它在导入名称下显示一条红色波浪线,并声称发生了错误,因为“没有名为“FreeCAD”的模块”,即使脚本运行良好。此外,PyCharm 无法在代码视图中提供代码补全,尽管它设法在 Python 控制台中提供代码补全。我正在创建新问题来解决这些问题,如果找到解决方案,我将在此处更新信息。