Importing PIL and gi into a Snap

python-pil and python-gi are python2 packages.

You’ll need to use the python3 equivalents - i.e python3-pil and python3-gi

I didn’t realise that, I only found those so assumed they would work for both. I can’t try it as my system disk is completely full, presumably something to do with snapbuilds which have failed, so I’ll have to find out how to delete that or I’ll have to re-install the OS.

Snap builds should not have filled your disk You could try using something like ncdu (https://dev.yorhel.nl/ncdu) to track down your disk usage.

I’m convinced it was something to do with Snap/LXD, as it’s the only thing I’ve done differently recently. I couldn’t use ncdu to check that though, as the system disk was so full I couldn’t even log in. It looks like a very effective utility though, better used on the first disk space warning…

I’ve reinstalled the system and had another go, and it’s getting a bit further. The app has a Glade GUI, it errors on this line:

gi.require_version(‘Gtk’, ‘3.0’)

so I assume that python3-gi contains a different version of Gtk. If I remove that line it presumably loads a different version of Gtk, but errors because of this line I think:

from gi.repository import Gtk, GdkPixbuf

Output:

chris@Dell-DXP051:~/myapp$ myapp
Traceback (most recent call last):
File “”, line 890, in _find_spec
AttributeError: ‘DynamicImporter’ object has no attribute ‘find_spec’

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File “myapp.py”, line 125, in
from gi.repository import Gtk, GdkPixbuf
File “/snap/myapp/x2/usr/lib/python3/dist-packages/gi/importer.py”, line 127, in find_module
‘introspection typelib not found’ % namespace)
ImportError: cannot import name Gtk, introspection typelib not found
chris@Dell-DXP051:~/myapp$

So maybe this is the error I need to investigate:

introspection typelib not found

No idea what that is though, and various posts about it refer to recompiling GTK3, which wouldn’t help as Snap is providing its own version I would think.

Try gir1.2-gtk-3.0 which is the introspection stuff for GTK itself

OK, but try what with it? Is it a Python thing?

from gi.repository import Gtk, GdkPixbuf, gir1.2-gtk-3.0

or perhaps

stage-packages:

  • python3
  • python-pil
  • python-gi
  • python-gir1.2-gtk-3.0

The GTK site https://www.gtk.org/download/linux.php mentions all these:

You will need to get the GLib, GObject-Introspection, Pango, Gdk-Pixbuf, ATK and GTK+ packages to build GTK+.
You may also need some of the external dependencies that are also linked for each version listed below.

But I can’t find the equivalent packages for them all here:

https://packages.ubuntu.com/artful/python/

the package name gir1.2-gtk-3.0 should be enough to add to the list of stage-packages for the GTK import.

GdkPixbuf is I think (could be wrong) met by the package gir1.2-gdkpixbuf-2.0

I’m still getting errors

chris@Dell-DXP051:~/myapp$ myapp
Traceback (most recent call last):
  File "<frozen importlib._bootstrap>", line 890, in _find_spec
AttributeError: 'DynamicImporter' object has no attribute 'find_spec'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "myapp.py", line 125, in <module>
    from gi.repository import Gtk, GdkPixbuf
  File "/snap/myapp/x9/usr/lib/python3/dist-packages/gi/importer.py", line 127, in find_module
    'introspection typelib not found' % namespace)
ImportError: cannot import name Gtk, introspection typelib not found
chris@Dell-DXP051:~/myapp$

Is there a logical way of tackling this, or is it trial and error? I couldn’t find a GTK+ forum.

You need to stage python3, python3-gi and gir1.2-gtk-3.0 for that error.

Thanks, I now have:
source: . # the directory in which snapcraft was executed.
plugin: dump
stage-packages:
- hugin # stage package for hugin - the official name
- gir1.2-gdkpixbuf-2.0
- python3-pil
after:
- python3
- python3-gi
- gir1.2-gtk-3.0

Which doesn’t work.

I have no idea whether this is the right way to do this. When I started making a Snap it looked as though it might be reasonably straightforward for my very simple Glade/Python app. It now appears to be getting more complicated by the minute. Am I going to have to spend a week or two learning about “Staging” and going deep into the complexities of how Python and GTK are connected? If that is the case, I might be better having a go at making a Flatpak (or pak-ing it in) as I have other things I could better spend the time on. Anyone give me some idea of how complex this is likely to get?

https://stackoverflow.com/questions/25037006/error-could-not-find-any-typelib-for-gtk-with-python3-and-gtk3 suggests this:
The problem should be solved by recompiling GTK (and its dependencies) with the configure option --enable-introspection=yes.

So is there is something wrong with GTK?

Hi there!

Got the same error here with a Ruby/GTK3 project : https://github.com/jbox-web/ssh-tunnel

/snap/ssh-tunnel/x1/lib/ruby/gems/2.5.0/gems/gobject-introspection-3.3.0/lib/gobject-introspection/loader.rb:37:in 'require': Typelib file for namespace 'Atk' (any version) not found (GObjectIntrospection::RepositoryError::TypelibNotFound)

After hours of digging I found out that /usr/lib/girepository-1.0 doesn’t exist from snap point of view :

nicolas@tchoum-desktop:~/PROJECTS/GITHUB/ssh-tunnel$ /var/lib/snapd/snap/bin/ssh-tunnel

# See https://github.com/jbox-web/ssh-tunnel/blob/master/lib/ssh-tunnel.rb#L11
/usr/lib/x86_64-linux-gnu/girepository-1.0
/usr/lib/girepository-1.0

ls: cannot access '/usr/lib/x86_64-linux-gnu/girepository-1.0': No such file or directory

ls: cannot access '/usr/lib/girepository-1.0': No such file or directory

# ls -hal /usr/lib
total 19K
drwxr-xr-x 36 root root  747 Nov  9 16:36 .
drwxr-xr-x 11 root root  151 Nov  9 16:36 ..
drwxr-xr-x  2 root root    3 Apr 12  2016 binfmt.d
drwxr-xr-x  2 root root   88 Nov  9 16:36 cloud-init
lrwxrwxrwx  1 root root   13 Nov  9 16:31 command-not-found -> /usr/bin/snap
drwxr-xr-x  2 root root   48 Nov  9 16:36 dbus-1.0
drwxr-xr-x  2 root root   37 Nov  9 16:36 environment.d
drwxr-xr-x  2 root root  105 Nov  9 16:36 fwupdate
drwxr-xr-x  4 root root   61 Nov  9 16:36 gcc
drwxr-xr-x  2 root root  118 Nov  9 16:36 gnupg
drwxr-xr-x  2 root root   40 Nov  9 16:36 grub
drwxr-xr-x  4 root root   53 Nov  9 16:36 i386-linux-gnu
drwxr-xr-x  4 root root   37 Nov  9 16:36 initramfs-tools
drwxr-xr-x  2 root root   98 Nov  9 16:36 initramfs-tools-ubuntu-core
drwxr-xr-x  2 root root   30 Nov  9 16:36 insserv
drwxr-xr-x  3 root root   26 Nov  9 16:36 klibc
-rw-r--r--  1 root root  19K May 25  2012 libnss_extrausers.so.2
drwxr-xr-x  3 root root   30 Apr 15  2016 locale
drwxr-xr-x  3 root root   65 Nov  9 16:36 mime
drwxr-xr-x  2 root root    3 Apr 12  2016 modules-load.d
drwxr-xr-x  2 root root   78 Nov  9 16:36 openssh
-rw-r--r--  1 root root  179 Nov  9 16:30 os-release
drwxr-xr-x  3 root root   30 Nov  9 16:36 pm-utils
drwxr-xr-x  3 root root   28 Nov  9 16:36 pppd
drwxr-xr-x  3 root root   36 Nov 10  2015 python2.7
drwxr-xr-x  3 root root   36 Nov 10  2015 python3
drwxr-xr-x 32 root root 3.6K Nov  9 16:36 python3.5
drwxr-xr-x  2 root root  630 Nov  9 16:36 rsyslog
lrwxrwxrwx  1 root root   19 Nov  5 12:26 sftp-server -> openssh/sftp-server
drwxr-xr-x  2 root root  399 Nov  9 16:36 snapd
drwxr-xr-x  3 root root   74 Nov  9 16:36 ssl
drwxr-xr-x  2 root root  295 Nov  9 16:36 sudo
drwxr-xr-x  8 root root  129 Nov  9 16:36 systemd
drwxr-xr-x  2 root root    3 Nov 10  2015 tar
drwxr-xr-x  2 root root  150 Nov  9 16:36 tc
drwxr-xr-x  2 root root  296 Nov  9 16:36 tmpfiles.d
drwxr-xr-x  2 root root   74 Nov  9 16:36 ubuntu-core-generic-initrd
drwxr-xr-x  2 root root   30 Nov  9 16:36 ubuntu-fan
drwxr-xr-x  2 root root   35 Nov  9 16:36 valgrind
drwxr-xr-x 14 root root 2.8K Nov  9 16:36 x86_64-linux-gnu
total 20K

# ls -hal /
drwxr-xr-x  24 root    root  321 Nov  9 16:36 .
drwxr-xr-x  24 root    root  321 Nov  9 16:36 ..
drwxr-xr-x   2 root    root 1.9K Nov  9 16:36 bin
drwxr-xr-x   6 root    root  129 Nov  9 16:36 boot
drwxr-xr-x  21 root    root 3.8K Dec  2 01:03 dev
drwxr-xr-x 107 root    root 4.0K Dec  2 01:34 etc
drwxr-xr-x  12 root    root 4.0K Oct 31 23:29 home
drwxr-xr-x  20 root    root  406 Nov  9 16:36 lib
drwxr-xr-x   2 root    root   43 Nov  9 16:36 lib64
drwxr-xr-x   3 root    root   60 Dec  2 01:44 media
drwxr-xr-x   3 root    root   45 Nov  9 16:36 meta
drwxr-xr-x   2 root    root 4.0K Oct  4 19:28 mnt
drwxr-xr-x   2 root    root    3 Nov  9 16:28 opt
dr-xr-xr-x 301 root    root    0 Dec  2 01:02 proc
drwxr-x---  11 root    root 4.0K Nov 30 19:32 root
drwxr-xr-x  35 root    root  980 Dec  2 01:04 run
drwxr-xr-x   2 root    root 2.3K Nov  9 16:36 sbin
drwxr-xr-x   7 root    root 4.0K Dec  2 03:12 snap
drwxr-xr-x   2 root    root    3 Nov  9 16:28 srv
dr-xr-xr-x  13 root    root    0 Dec  2 01:02 sys
drwxrwxrwt   2 nicolas lxd    40 Dec  2 03:13 tmp
drwxr-xr-x  11 root    root  151 Nov  9 16:36 usr
drwxr-xr-x  12 root    root  160 Nov  9 16:36 var
drwxr-xr-x   2 root    root    3 Nov  9 16:30 writable
/snap/ssh-tunnel/x1/lib/ruby/gems/2.5.0/gems/atk-3.3.0/lib/atk.rb:27: warning: already initialized constant Atk::LOG_DOMAIN
/snap/ssh-tunnel/x1/lib/ruby/gems/2.5.0/gems/atk-3.3.0/lib/atk.rb:27: warning: previous definition of LOG_DOMAIN was here
Traceback (most recent call last):
	15: from /snap/ssh-tunnel/x1/bin/ssh-tunnel:23:in `<main>'
	14: from /snap/ssh-tunnel/x1/bin/ssh-tunnel:23:in `load'
	13: from /snap/ssh-tunnel/x1/lib/ruby/gems/2.5.0/gems/ssh-tunnel-1.0.0/bin/ssh-tunnel:6:in `<top (required)>'
	12: from /snap/ssh-tunnel/x1/lib/ruby/2.5.0/rubygems/core_ext/kernel_require.rb:59:in `require'
	11: from /snap/ssh-tunnel/x1/lib/ruby/2.5.0/rubygems/core_ext/kernel_require.rb:59:in `require'
	10: from /snap/ssh-tunnel/x1/lib/ruby/gems/2.5.0/gems/ssh-tunnel-1.0.0/lib/ssh-tunnel.rb:10:in `<top (required)>'
	 9: from /snap/ssh-tunnel/x1/lib/ruby/gems/2.5.0/gems/ssh-tunnel-1.0.0/lib/ssh-tunnel.rb:18:in `rescue in <top (required)>'
	 8: from /snap/ssh-tunnel/x1/lib/ruby/2.5.0/rubygems/core_ext/kernel_require.rb:59:in `require'
	 7: from /snap/ssh-tunnel/x1/lib/ruby/2.5.0/rubygems/core_ext/kernel_require.rb:59:in `require'
	 6: from /snap/ssh-tunnel/x1/lib/ruby/gems/2.5.0/gems/gtk3-3.3.0/lib/gtk3.rb:18:in `<top (required)>'
	 5: from /snap/ssh-tunnel/x1/lib/ruby/2.5.0/rubygems/core_ext/kernel_require.rb:59:in `require'
	 4: from /snap/ssh-tunnel/x1/lib/ruby/2.5.0/rubygems/core_ext/kernel_require.rb:59:in `require'
	 3: from /snap/ssh-tunnel/x1/lib/ruby/gems/2.5.0/gems/atk-3.3.0/lib/atk.rb:26:in `<top (required)>'
	 2: from /snap/ssh-tunnel/x1/lib/ruby/gems/2.5.0/gems/atk-3.3.0/lib/atk.rb:34:in `<module:Atk>'
	 1: from /snap/ssh-tunnel/x1/lib/ruby/gems/2.5.0/gems/gobject-introspection-3.3.0/lib/gobject-introspection/loader.rb:37:in `load'
/snap/ssh-tunnel/x1/lib/ruby/gems/2.5.0/gems/gobject-introspection-3.3.0/lib/gobject-introspection/loader.rb:37:in `require': Typelib file for namespace 'Atk' (any version) not found (GObjectIntrospection::RepositoryError::TypelibNotFound)

The weird thing is that required files exist in /snap/ssh-tunnel/current/ :

nicolas@tchoum-desktop:/snap/ssh-tunnel/current$ find . -name *.typelib
./usr/lib/girepository-1.0/Atk-1.0.typelib
./usr/lib/girepository-1.0/Atspi-2.0.typelib
./usr/lib/x86_64-linux-gnu/girepository-1.0/DBus-1.0.typelib
./usr/lib/x86_64-linux-gnu/girepository-1.0/DBusGLib-1.0.typelib
./usr/lib/x86_64-linux-gnu/girepository-1.0/GIRepository-2.0.typelib
./usr/lib/x86_64-linux-gnu/girepository-1.0/GL-1.0.typelib
./usr/lib/x86_64-linux-gnu/girepository-1.0/GLib-2.0.typelib
./usr/lib/x86_64-linux-gnu/girepository-1.0/GModule-2.0.typelib
./usr/lib/x86_64-linux-gnu/girepository-1.0/GObject-2.0.typelib
./usr/lib/x86_64-linux-gnu/girepository-1.0/Gdk-3.0.typelib
./usr/lib/x86_64-linux-gnu/girepository-1.0/GdkPixbuf-2.0.typelib
./usr/lib/x86_64-linux-gnu/girepository-1.0/GdkX11-3.0.typelib
./usr/lib/x86_64-linux-gnu/girepository-1.0/Gio-2.0.typelib
./usr/lib/x86_64-linux-gnu/girepository-1.0/Gtk-3.0.typelib
./usr/lib/x86_64-linux-gnu/girepository-1.0/Pango-1.0.typelib
./usr/lib/x86_64-linux-gnu/girepository-1.0/PangoCairo-1.0.typelib
./usr/lib/x86_64-linux-gnu/girepository-1.0/PangoFT2-1.0.typelib
./usr/lib/x86_64-linux-gnu/girepository-1.0/PangoXft-1.0.typelib
./usr/lib/x86_64-linux-gnu/girepository-1.0/cairo-1.0.typelib
./usr/lib/x86_64-linux-gnu/girepository-1.0/fontconfig-2.0.typelib
./usr/lib/x86_64-linux-gnu/girepository-1.0/freetype2-2.0.typelib
./usr/lib/x86_64-linux-gnu/girepository-1.0/libxml2-2.0.typelib
./usr/lib/x86_64-linux-gnu/girepository-1.0/xfixes-4.0.typelib
./usr/lib/x86_64-linux-gnu/girepository-1.0/xft-2.0.typelib
./usr/lib/x86_64-linux-gnu/girepository-1.0/xlib-2.0.typelib
./usr/lib/x86_64-linux-gnu/girepository-1.0/xrandr-1.3.typelib

So they are already contain in the snap package.

That’s why I say : /usr/lib/girepository-1.0 doesn’t exist from (within) snap point of view.

Here my snapcraft.yaml.

I don’t know (yet) how snap fs works, if it’s a bug or a feature, but these files are not visible when the application starts.

Does anyone have a lead to fix this?

You can either use the layouts feature to remap $SNAP/usr/lib/x86_64-linux-gnu/girepository-1.0 to /usr/lib/x86_64-linux-gnu/girepository-1.0 or augment the environment variable GI_TYPELIB_PATH. Using the desktop-gtk3 part will set this automatically, but you can write your own wrapper to set it yourself. The relevant code from the GTK3 desktop helper is:

function prepend_dir() {
  local var="$1"
  local dir="$2"
  if [ -d "$dir" ]; then
    eval "export $var=\"\$dir\${$var:+:\$$var}\""
  fi
}

prepend_dir GI_TYPELIB_PATH $SNAP/usr/lib/$ARCH/girepository-1.0
prepend_dir GI_TYPELIB_PATH $SNAP/usr/lib/girepository-1.0
prepend_dir GI_TYPELIB_PATH $SNAP/usr/lib/gjs/girepository-1.0

Hi Daniel!

Thank you for your quick answer! I use desktop-gtk3 as explain in Desktop App Support - GTK.

I’ve got one more question : the application starts \o/ but I’ve got this messages in the console

Gtk-Message: Failed to load module "canberra-gtk-module"
Gtk-Message: Failed to load module "canberra-gtk-module"
XMLLINT not set and xmllint not found in path; skipping xml preprocessing.
Gtk-WARNING **: Error loading theme icon 'list-add' for stock: Icon 'list-add' not present in theme Adwaita

and buttons icons are not visible :confused:

Any hints?

Thank you!

i’d start with adding libxml2-utils to stage-packages so that the xmllint binary is in your snap, perhaps the second error goes away with that too already :slight_smile: … (the first two lines are “normal” for apps with the desktop wrappers, you can ignore them)

@bashfulrobot I now think it’s more likely to have been Flatpak filling up my system disk.

After a very long Web search for something useful, I’ve got the Snap to work for “from PIL import Image”. In the snapcraft.yaml below, either of the “Parts:” blocks will work. It’s the “Wrapper:” block that was missing.

name: pil
version: '0'
summary: test
description: |
  Test

grade: devel
confinement: devmode

apps:
  pil:
    command: python3 $SNAP/pil.py
#=======================================

parts:
#-------------------
  main-part:
    plugin: python
    python-packages:
      - pillow
#-------------------
#  main-part:
#    plugin: python
#    stage-packages:
#      - python3-pil
#-------------------

  wrapper: 
    plugin: dump
    

Give me another year and I might get “from gi.repository import Gtk, GdkPixbuf” to work :frowning: .

Hi @ChrisOfBristol,

I am having the same issue, the snap does not see the libraries in usr/lib/$ARCH . So I am not able to run gi.repository import GObject.

Have you found the solution for this?

I actually found the solution for this.

In the snap -apps:

You will have to include: this line in the environment:

   GI_TYPELIB_PATH: $SNAP/usr/lib/x86_64-linux-gnu/girepository-1.0

Then it works

@rahul-tt It was considerate of you to post the answer. However I have long ago given up on Snap and have published the application as a Flatpak instead.