Better method for installing Python dependencies

I have been developing several Glyphs plugins that require external Python dependencies (examples include NumPy, Pillow, Mido). I understand from this topic that I can symlink or manually add the paths to the libraries. However, the above packages are not simply single folders that I can locate and copy. For example, Mido has other dependencies that I am not completely familiar with, so I wouldn’t know which libraries I would need; NumPy is compiled so it contains non-Python libraries which are scattered in different places.

I could install a custom version of Python, install pyobjc and these libraries and change the version in Preferences. However, I don’t think this is easy to follow for non-developers and any end-user.

All this is to say that I wish there could be a better way to install and manage packages for the Glyphs version of Python. The back-end of it should be relatively straightforward as Pip already does all the dependency management.

In the meantime, is there any way to install packages into Glyph’s version of Python?

You can install it into the ~/Library/Application Support/Glyphs 3/Scripts/site-packages.
you need to find a python 3.10, then you can run this:

/Library/Frameworks/Python.framework/Versions/3.10/bin/pip3  install --target="/Users/YOUR USER NAME/Library/Application Support/Glyphs 3/Scripts/site-packages" numpy

You need to replace “YOUR USER NAME” with the name of your user folder.

1 Like

Hi thanks! I was wondering if there is an easier method to install packages - say, if I want a non-developer user to use my plugin. Could there be a simple GUI for pip?

I’ll think about it.

1 Like

you need to find a python 3.10, then you can run this:

The default Python in 3.2(3205) is 3.9.1

Here’s a cut-and-pastable that seems to have worked for me

python3.9 -m pip install --target="/Users/$USER/Library/Application Support/Glyphs 3/Scripts/site-packages" numpy

It’s already 3.11. To upgrade your Python, just uninstall and reinstall the module.

Thanks for this. Just to clarify:

  • You would need an additional copy of Python in order for @SimonC 's method to work. This copy has to be in the same version as Glyphs’s Python.
  • Glyphs’s Python module does not come with its own pip, hence we need to use pip from another copy of Python.
  • Once you uninstall and reinstall the Python module in Glyphs, all previously installed pip libraries would be gone and would need to be reinstalled.

Are these correct?

The first two points are true. The third is not. The mentioned folder is outside the Glyphs python module.

1 Like

I’m also having difficulty installing dependencies, specifically numpy. It would be nice if I could just point Glyphs at my installed copy of Python3 but the only Python3 version in settings is “3.10.11 (Glyphs)”. Python install hell makes me long for DLL hell. @SimonC’s suggestion worked in the sense that it installed numpy in site-packages, but import still couldn’t find it. I moved it one level up (to Scripts rather than Scripts/site-packages) and I now get an actual error:

IMPORTANT: PLEASE READ THIS FOR ADVICE ON HOW TO SOLVE THIS ISSUE!

Importing the numpy C-extensions failed. This error can happen for
many reasons, often due to issues with your setup or how NumPy was
installed.

We have compiled some common reasons and troubleshooting tips at:

    https://numpy.org/devdocs/user/troubleshooting-importerror.html

Please note and check the following:

  * The Python version is: Python3.10 from "/Applications/Glyphs 3.app/Contents/MacOS/Glyphs 3"
  * The NumPy version is: "1.26.0"

and make sure that they are the versions you expect.
Please carefully study the documentation linked above for further help.

Original error was: No module named 'numpy.core._multiarray_umath'

To get the latest version of the GlyphsPython module, remove and reinstall it in the Plugin Manager. That will give you Python 3.11

You need to download Python 3.11 from python.org and install it. Then install all needed libs there (with pip3.11 install … you make sure to use the just installed version).
Or use pip with the -t option and specify this path: ~/Library/Application Support/Glyphs 3/Scripts/site-packages/ (replace the ~ with the path of your user folder). Then the libs will be available in Glyphs even with the Glyphs Python.

I just uninstalled Python from plugin manager and reinstalled. Quit Glyphs and restarted. It’s still Python 3.10.11 which is what Settings says and what Python says:

>>> print(sys.version_info)
sys.version_info(major=3, minor=10, micro=11, 
    releaselevel='final', serial=0)

My Glyphs version is 3.1.2 (3151) which Check for Updates says is the latest version. Latest Python is of course 3.12 although 3.11 is fine for me if that’s what Glyphs will work with, if I could get it.

I also tried removing Python, quitting and restarting. When I started it up it asked if I wanted to install Python as I had a plugin that required it. I said OK. Going to Plugin Manager says it’s installed. But going to Macro Panel, and trying to run code there says “There is no compatible version of Python 3 installed.” I finally got Python working again by uninstalling the Python module, quitting and restarting and not letting it install it automatically for me, manually installing in the plugin manager, quitting and restarting. But numpy still isn’t working.

Also, the dialog that a plugin crashed is very confusing. It advises “remove and reinstall them” and the choices are ignore, remove, and ok. I don’t want to remove them of course but I don’t know what ignore does vs ok. What I want is for it to not remove them but not crash again because Python isn’t there and use them again next time. So I clicked OK. That seemed to work. But the messaging could be clearer.

I forgot. 3.11 is only available in Glyphs 3.2 (cutting edge at the moment). But the above explanation should work with 3.10, too.

Couldn’t you @GeorgSeifert add pip to the Glyphs Python Plugin, so installing stuff could be easier?

Allowing any plugin or macro to invoke pip without the user noticing would be a security risk, but perhaps plugins could declare some dependencies that the user would then be prompted to get installed. And for things you want to install yourself, a simple dialog box where you enter the names of Python packages which would then be installed in the right place?

2 Likes

I just uploaded a new version of the Glyphs Python that includes pip. Only for the 3.2 python, yet.

Is there a new Glyphs build to go with the new Python? I get

 File "plugin.py", line 2, in <module>
    from GlyphsApp import *

ImportError: bad magic number in 'GlyphsApp': b'\xc4\r\r\n'

I think the compiled wrapper is not built for Python 3.12 yet.

Yes. I reverted it. Please remove and re-install.

Once I remove and install the python module on Glyphs 3.2 and restart, it show that that 3.11 is installed…how do you use pip to install numpy, for example?

In theory, running something like this from the Macro Panel should work:

import pip
from pathlib import Path
install_dir = Path.home() / "Library" / "Application Support" / "Glyphs 3" / "Scripts"
args = ["install", "-t", install_dir, "-U", "numpy"]
pip.main(args)

But it doesn’t, because pip doesn’t like to be called from inside a script:

WARNING: pip is being invoked by an old script wrapper. This will fail in a future version of pip.
Please see https://github.com/pypa/pip/issues/5599 for advice on fixing the underlying issue.
To avoid this problem you can invoke Python with '-m pip' instead of running pip directly.
Traceback (most recent call last):
  File "<macro panel>", line 5
  File "__init__.py", line 13, in main
    return _wrapper(args)
           ^^^^^^^^^^^^^^
  File "entrypoints.py", line 43, in _wrapper
    return main(args)
           ^^^^^^^^^^
  File "main.py", line 77, in main
    command = create_command(cmd_name, isolated=("--isolated" in cmd_args))
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "__init__.py", line 114, in create_command
    module = importlib.import_module(module_path)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<frozen importlib._bootstrap>", line 1204, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1176, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1147, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 690, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 940, in exec_module
  File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
  File "install.py", line 15
    from pip._internal.cli.req_command import (
  File "req_command.py", line 21
    from pip._internal.index.package_finder import PackageFinder
  File "package_finder.py", line 30
    from pip._internal.req import InstallRequirement
  File "__init__.py", line 8
    from .req_install import InstallRequirement
  File "req_install.py", line 36
    from pip._internal.operations.build.metadata_legacy import (
  File "metadata_legacy.py", line 14
    from pip._internal.utils.setuptools_build import make_setuptools_egg_info_args
ModuleNotFoundError: No module named 'pip._internal.utils.setuptools_build'

I should also be possible to run pip via subprocess, but it doesn’t work either (no error message …):

import subprocess
from pathlib import Path
python = Path.home() / "Library" / "Application Support" / "Glyphs 3" / "Repositories" / "GlyphsPythonPlugin" / "Python.framework" / "Versions" / "Current" / "bin" / "python3"
install_dir = Path.home() / "Library" / "Application Support" / "Glyphs 3" / "Scripts"
args = [f"'{python}'", "-m", "pip", "install", "-t", f"'{install_dir}'", "-U", "numpy"]
try:
	r = subprocess.check_output(args, stderr=subprocess.STDOUT, shell=True)
except subprocess.CalledProcessError as e:
	print(e.returncode)
	print(e.output)
print(r)

This works from the command line:

~/Library/Application\ Support/Glyphs\ 3/Repositories/GlyphsPythonPlugin/Python.framework/Versions/Current/bin/pip3 install -t ~/Library/Application\ Support/Glyphs\ 3/Scripts numpy

EDIT: Only if you also have the python.org Python 3.11 installed. I’m giving up :wink: