Importing Python Libraries

Hi together,

I have tried to emplement a new Interface which relies on other python packages. Most of them are internal packages lying on local pypi. I tried package the packages with the LibraryBuilder2 and I crash at this point:
INFO:LibraryBuilder64:Deleting virtual environment C:\Users\user\Documents\SweepMe\librarybuilder\libraries\venv64
INFO:LibraryBuilder64:Inspecting libs
WARNING:LibraryBuilder64:{‘share/man/man1/ipython.1’}
WARNING:LibraryBuilder64:The files listed above could not be assigned to any python package. The created libs might not work without them.
WARNING:LibraryBuilder64:{‘pyqt6’, ‘pyside6-essentials’, ‘internal’, ‘pyside6-addons’, ‘shiboken6’, ‘internal-gen’, ‘pyqt6-qt6’, ‘lxml’}
WARNING:LibraryBuilder64:The libraries listed above have a more complex structure. The LibraryBuilder cannot handle these and needs to be extended to support them. Please contact the SweepMe! developers.
ERROR:LibraryBuilder64:Traceback (most recent call last):
File “LibraryBuilder2.py”, line 73, in build
File “PackageFixer.py”, line 185, in fix_libs
File “PackageFixer.py”, line 180, in process_actions
Exception: Libraries could not be packaged correctly.

I can get the internal packages as whl files. How can I import them into my custom implementation to use with sweepme?

Thanks in advance.
Marc

1 Like

Hi,

thanks for sharing the details. Let me summarize and clarify a few important aspects so we can move forward:

Custom GUI and SweepMe! Compatibility

I assume you are writing a custom GUI for a CustomFunction script? Please note that SweepMe! uses PySide2/Qt5 internally. This means the SweepMe! process already runs within a PySide2-based GUI ecosystem.
If you try to load packages like PySide6 or PyQt6, they will conflict with the existing Qt runtime because different Qt versions cannot coexist in the same Python process (and I wouldn’t recommend mixing PySide and PyQt either).
For this reason, you must stick to PySide2 when creating custom GUIs for SweepMe!. This should eliminate the need to bundle the Qt6 bindings and dependencies. Please let me know if I misunderstood your intentions and your interface is something different.


“internal” Package from PyPI

At first glance, the internal package does not look structurally complex, so it should have worked. However, it appears to be available only for Python 3.11 and above, while SweepMe! is based on Python 3.9.
Could you confirm that you are writing your interface with Python 3.9 compatibility in mind and use the LibraryBuilder2 with a Python 3.9 64bit installation (configured in the LibraryBuilder2.ini)? Also, please let me know:

  • Which version of internal you are using.
  • Whether you are using the official package from PyPI or a custom/internal build.

If possible, please send me the requirements.txt you used for LibraryBuilder2. This will help me reproduce your setup and investigate further, so we can get your code running.

Hi Felix,
thanks for your reply. First of all, the “internal” package was a mask from my side since I am not allowed to share names of internal sources, so I just renamed the printout in “internal” and “internal-gen”. They also can be installed through the mapping to a local pypi which according to the logs also is working.
I am not trying to write a customfunction. I wanted to add a new device, which has also a gui part in there. I am at the moment more interested in the functionality of the rest of the package and not the gui part but this would be a really nice to have addon. Since this package is a internal other source I cannot change the implementation of it. The QT and Pyside part is only used for the gui.
Maybe there is than another way around this?
Greetings
Marc

Ah, I see. Thanks for the explanation. Let me clarify a few important points and outline possible solutions:


No direct GUI support in drivers

SweepMe! runs measurements in a separate thread to keep the main application responsive. However, any GUI operation must be executed in the main thread because Qt (and most GUI frameworks) are not thread-safe.
If GUI code runs in the measurement thread, you risk random freezes or crashes. This is why drivers cannot simply display their own custom GUI.


internal package

From what you describe, the internal package seems to have:

  • GUI parts (requiring PySide6/Qt6)
  • Non-GUI parts (e.g., instrument communication)

The key question:
Do the non-GUI parts work without having Qt6/PySide6 installed? If yes, we can go with Option A.


Option A: Manual library integration

I’m already surprised the LibraryBuilder2 works with a local pypi repository. But it does not understand the internal package and most likely cannot be adjusted without leaking some package details.
Therefore I would suggest to manually add your internal packages:

  1. Identify the dependencies of your internal packages.
  2. Use LibraryBuilder2 to install these dependencies and other packages you want to use, but exclude internal and the GUI packages. (the error for the lxml package should be fixed now)
  3. Install your internal package in a temporary Python 3.9 64bit environment.
  4. Copy the relevant folder from the site-packages into SweepMe!’s libs_39_64 folder.

This way, you avoid Qt conflicts and still use the non-GUI functionality.


Option B: When Qt6/PySide6 is required

If the package cannot be imported without Qt6:

  • Qt6 and PySide6 cannot coexist with SweepMe!’s PySide2/Qt5 in the same process.
  • The conceptual solution is to split the driver into two parts:
    • Part 1: A conventional SweepMe! driver structure (without the conflicting libraries).
    • Part 2: A separate process that can freely import almost any package (like internal, PySide2), and even create a GUI.
  • Such cases, where a necessary library for the driver conflicts with a SweepMe! library, are quite rare, but we have a library interface-proxy which provides some helper functions for a simple communication between the processes of the two parts of the driver.

This approach is much more complex but avoids runtime conflicts.


I recommend trying Option A first, as it’s simpler and could already work. If it doesn’t, we can dive deeper into Option B.

Let me know if I should go more into detail for a certain step or if you run into new errors.