How to embed FreeCAD in a Python virtual environment?

5.4k views Asked by At

How do I setup a Python virtual environment with the FreeCAD library embedded as to enable import as a module into scripts?

I would like to avoid using the FreeCAD GUI as well as being dependent on having FreeCAD installed on the system, when working with Python scripts that use FreeCAD libraries to create and modify 3D geometry. I hope a Python virtual environment can make that possible.

I am working in PyCharm 2021.1.1 with Python 3.8 in virtualenv on Debian 10.

I started out with FreeCAD documentation for embedding in scripts as a basis:

https://wiki.freecadweb.org/Embedding_FreeCAD

In one attempt, I downloaded and unpacked .deb packages from Debian, taking care to get the correct versions required by each dependency. In another attempt, I copied the contents of a FreeCAD flatpak install, as it should contain all the libraries that FreeCAD depends on.

After placing the libraries to be imported in the virtual maching folder, I have pointed to them with sys.path.append() as well as PyCharm's Project Structure tool in various attempts. In both cases the virtual environment detects where FreeCAD.so is located, but fails to find any of its dependencies, even when located in the same folder. When importing these dependencies explicitly, each of them have the same issue. This leads to a dead end when an import fails because it does not define a module export function according to Python:

ImportError: dynamic module does not define module export function (PyInit_libnghttp2)

I seem to be looking at a very long chain of broken dependencies, even though I make the required libraries available and inform Python where they are located.

I would appreciate either straight up instructions for how to do this or pointers to documentation that describes importing FreeCAD libraries in Python virtual environments, as I have not come across anything that specific yet.

I came across a few prior questions which seemed to have similar intent, but no answers:

Embedding FreeCAD in python script

Is it possible to embed Blender/Freecad in a python program?

Similar questions for Conda focus on importing libraries from the host system rather than embedding them in the virtual environment:

Incude FreeCAD in system path for just one conda virtual environment

Other people's questions on FreeCAD forums went unanswered:

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

EDIT:

Figuring this out was a great learning experience. The problem with piecing dependencies together is that for that approach to work out, everything from the FreeCAD and its dependencies to the Python interpreter and its dependencies seems to need to be built on the same versions of the libraries that they depend on to avoid causing segmentation faults that brings everything to a crashing halt. This means that the idea of grabbing FreeCAD modules and libraries it depends on from a Flatpak installation is in theory not horrible, as all parts are built together using the same library versions. I just couldn't make it work out, presumably due to how the included libraries are located and difficulty identifying an executable for the included Python interpreter. In the end, I looked into the contents of the FreeCAD AppImage, and that turned out to have everything needed in a folder structure that appears to be very friendly to what PyCharm and Python expects from modules and libraries.

1

There are 1 answers

4
tompi On BEST ANSWER

This is what I did to get FreeCAD to work with PyCharm and virtualenv:

Download FreeCAD AppImage

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

Make AppImage executable

chmod -v +x ~/Downloads/FreeCAD_*.AppImage

Create folder for extracting AppImage

mkdir -v ~/Documents/freecad_appimage

Extract AppImage from folder (note: this expands to close to 30000 files requiring in excess of 2 GB disk space)

cd ~/Documents/freecad_appimage

~/Downloads/./FreeCAD_*.AppImage --appimage-extract 

Create folder for PyCharm project

mkdir -v ~/Documents/pycharm_freecad_project

Create pycharm project using Python interpreter from extracted AppImage

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

Add folder containing FreeCAD.so library as Content Root to PyCharm Project Structure and mark as Sources (by doing so, you shouldn't have to set PYTHONPATH or sys.path values, as PyCharm provides module location information to the interpreter)

File: Settings: Project: Project Structure: Add Content Root
~/Documents/freecad_appimage/squashfs-root/usr/lib

After this PyCharm is busy indexing files for a while.

Open Python Console in PyCharm and run command to check basic functioning

import FreeCAD

Create python script with example functionality

import FreeCAD
vec = FreeCAD.Base.Vector(0, 0, 0)
print(vec)

Run script

Debug script

All FreeCAD functionality I have used in my scripts so far has worked. However, one kink seems to be that the FreeCAD module needs to be imported before the Path module. Otherwise the Python interpreter exits with code 139 (interrupted by signal 11: SIGSEGV).

There are a couple of issues with PyCharm: It is showing a red squiggly line under the import name and claiming that an error has happened because "No module named 'FreeCAD'", even though the script is running perfectly. Also, PyCharm fails to provide code completion in the code view, even though it manages to do so in it's Python Console. I am creating new questions to address those issues and will update info here if I find a solution.