Python dlopen()s musl libc

  • Open
  • quality assurance status badge
Details
4 participants
  • Josselin Poiret
  • Lars-Dominik Braun
  • Ludovic Courtès
  • Athena Martin
Owner
unassigned
Submitted by
Athena Martin
Severity
normal
A
A
Athena Martin wrote on 27 Jun 2023 02:42
(address . bug-guix@gnu.org)
20230626204230.7b3b773a@spock.hosts.alm.website
I've had experiences now with multiple Guix packages, including gajim
(bug 60235) and now python-neovim-remote, which have an issue where
Python tries to dlopen() libc, but finds the system libc instead of
Guix's, resulting on Alpine Linux hosts in a crash with this message:

ImportError: libc.musl-x86_64.so.1: cannot open shared object file: No such file or directory

There are a variety of tracebacks that lead up to this, depending on
the package in question.
-----BEGIN PGP SIGNATURE-----

iQEzBAEBCgAdFiEELAGoSzc6nHIdbhP+S8DcQuG8sXMFAmSaMHYACgkQS8DcQuG8
sXNzwwf/QSs5nNKbTPCDx+ucfoiR1bYTS40WHqBfPvccKoXJ01sGgh332OpRlyMb
ggXdFOjtcTrZqnTNzYOpU5JvE6zWLWNj2Za5Uz4SXWWTX/0E+t93jyQdrDqF0NNr
MheYJ+cSHO5SclaezT60lom3FS9KttQHDaS6IUfDFnMdCtNpnUvFE+hUH55XJmSc
My/kFy1Rv8OgeB5jPj+Kf6I1Fn2n0m68dWenzyjn0GMJl4Wu8qvUlvTz1erDEARE
vKAZdFXmkUKaZEGYL9gC9uf3k1Vf2gUJu0nG/hNhfbb9c6CQbGPiMJNk8xy78DwO
TlDn8/GS/yHryjyeHrS7DbtYPQWz+Q==
=Bjwl
-----END PGP SIGNATURE-----


L
L
Ludovic Courtès wrote on 7 Jul 2023 16:00
(name . Athena Martin)(address . secure@alm.website)(address . 64309@debbugs.gnu.org)
87mt07kej7.fsf@gnu.org
Hi,

Athena Martin <secure@alm.website> skribis:

Toggle quote (10 lines)
> I've had experiences now with multiple Guix packages, including gajim
> (bug 60235) and now python-neovim-remote, which have an issue where
> Python tries to dlopen() libc, but finds the system libc instead of
> Guix's, resulting on Alpine Linux hosts in a crash with this message:
>
> ImportError: libc.musl-x86_64.so.1: cannot open shared object file: No such file or directory
>
> There are a variety of tracebacks that lead up to this, depending on
> the package in question.

Could you provide a command to reproduce this?

Thanks in advance,
Ludo’.
L
L
Ludovic Courtès wrote on 7 Jul 2023 16:00
control message for bug #64309
(address . control@debbugs.gnu.org)
87lefrkeiv.fsf@gnu.org
tags 64309 + moreinfo
quit
A
A
Athena Martin wrote on 8 Jul 2023 22:16
Re: bug#64309: Python dlopen()s musl libc
(name . Ludovic Courtès)(address . ludo@gnu.org)(address . 64309@debbugs.gnu.org)
20230708161658.25be509c@spock.hosts.alm.website
Toggle quote (5 lines)
> > ImportError: libc.musl-x86_64.so.1: cannot open shared object file:
> > No such file or directory
>
> Could you provide a command to reproduce this?

On an Alpine Linux Edge host, I reproduce with:

$ guix install python-neovim-remote
$ nvr

It's possible that there's some quirk of my specific environment.

(I'm currently in the process of switching to Guix System so I may not
be able to reproduce this forever.)
-----BEGIN PGP SIGNATURE-----

iQEzBAEBCgAdFiEELAGoSzc6nHIdbhP+S8DcQuG8sXMFAmSpxDoACgkQS8DcQuG8
sXN83wf/V7A5dV7nXevxTWjWXnMU5SvzC0zdjhXExa1rVn9xMKKbai8+SSAHzAkF
EGFvq6TUc3oTNG7ErrPpsV/AyIVli1tCcLJhreBt1M75ZHi1vX0ccRveJjrk5vk3
eHhYY903rnFfY9kihCMQqMnBnNynhovr3MJc2gdM3khQgFy8VwruCf23zPQahrdT
C6GEfO76w7dQ10SorJuh1U4gsslxfOZe1bLCprZaOgqaHHO+RAxdKVEgr7o4FVMb
SjSPjWvSwuBocRE8VzkZsRdZpZZTHB0m9OuPPNufIO+joYyhu6EECG1gwxajKNix
yr4oXdPH3vVwV/vcO6tTrV2ByKEjrg==
=/syo
-----END PGP SIGNATURE-----


J
J
Josselin Poiret wrote on 9 Jul 2023 10:35
(address . 64309@debbugs.gnu.org)
87v8et8oug.fsf@jpoiret.xyz
Hi Athena,

Athena Martin via Bug reports for GNU Guix <bug-guix@gnu.org> writes:

Toggle quote (10 lines)
> On an Alpine Linux Edge host, I reproduce with:
>
> $ guix install python-neovim-remote
> $ nvr
>
> It's possible that there's some quirk of my specific environment.
>
> (I'm currently in the process of switching to Guix System so I may not
> be able to reproduce this forever.)

Can you do `LD_DEBUG=libs nvr` so that we get a log of what ld's trying
to load?

Best,
--
Josselin Poiret
-----BEGIN PGP SIGNATURE-----

iQHEBAEBCgAuFiEEOSSM2EHGPMM23K8vUF5AuRYXGooFAmSqcTcQHGRldkBqcG9p
cmV0Lnh5egAKCRBQXkC5FhcaiiF/DACciRfBYJ+TwYI/WIIxrl3y+RL811Lcr/bO
EyeAMQ8DXXqLBCodGIwZRmBGz3QLwLeljD3tcUTnftCLlWu4n/ZFLOAEi2xlXsrw
ONQfntDvpItjQms7TEepd8nMjiMyV4OdTP+2i1AjpXu6c3JIUBwySZ40PRZh+G4F
gWR5lhodGpmPLTFKIWSVVgn6O/9OA7mvauaAN0iI2zWoSsv4dIbPln07HZZBemvb
FE76YWHu4KUpVMA+NynNBvb4T5vtg55h8ou3t6ak1KdOTMaXMGYNVPZqE05P+GLi
ERyyFeSBON4kH2P2og1VRdpJbU5njtu2EPz2H6C8eUjsNG29AzMaDCHX8V2LzmA4
BMxvBVbdx4B1THfPKvOXG2X7NpDaRAIRXnMvnEEEoiMCmyIQHFXMXajjf6/xVPaA
ZXrf38nh/6DBxvhDfpHEFR2NhhtKpq9mDtwHzeiOytY3wnrqglxarQaDMequ24sA
Eq1h4s/ROMtzxVTIMuiJAcYp8EYtsEM=
=xBoh
-----END PGP SIGNATURE-----

A
A
Athena Martin wrote on 9 Jul 2023 22:22
(name . Josselin Poiret)(address . dev@jpoiret.xyz)
20230709162221.39fb0e66@spock.hosts.alm.website
Toggle quote (3 lines)
> Can you do `LD_DEBUG=libs nvr` so that we get a log of what ld's
> trying to load?

I've attached the full log. The first mention of musl is on line 200 and
everything seems to happen pretty fast, here's the most relevant
portion:

16405: find library=libc.musl-x86_64.so.1 [0]; searching
16405: search cache=/gnu/store/kj6wzba6p192baizq99b489rs8bynpn7-python-3.10.7/etc/ld.so.cache
16405: search path=/gnu/store/gsjczqir1wbz8p770zndrpw4rnppmxi3-glibc-2.35/lib (system search path)
16405: trying file=/gnu/store/gsjczqir1wbz8p770zndrpw4rnppmxi3-glibc-2.35/lib/libc.musl-x86_64.so.1
16405:
Traceback (most recent call last):
File "/gnu/store/dsgxdqs620pp284bfm1drbsjqpb36i4n-python-neovim-remote-2.5.1/bin/.nvr-real", line 4, in <module>
import nvr.nvr as mod
File "/home/alm/.local/lib/python3.10/site-packages/nvr/__init__.py", line 1, in <module>
from .nvr import main
File "/home/alm/.local/lib/python3.10/site-packages/nvr/nvr.py", line 34, in <module>
import psutil
File "/home/alm/.local/lib/python3.10/site-packages/psutil/__init__.py", line 102, in <module>
from . import _pslinux as _psplatform
File "/home/alm/.local/lib/python3.10/site-packages/psutil/_pslinux.py", line 26, in <module>
from . import _psutil_linux as cext
ImportError: libc.musl-x86_64.so.1: cannot open shared object file: No such file or directory

After that it starts calling fini()s and terminates.
Attachment: stderr.log
-----BEGIN PGP SIGNATURE-----

iQEzBAEBCgAdFiEELAGoSzc6nHIdbhP+S8DcQuG8sXMFAmSrFv0ACgkQS8DcQuG8
sXOxAAgAjot+pPtMO79F5afeokuVMiERpmPlw0uDSLsQ/+ivt2WaupOAm7Ag9sdg
MgeecEF1qWRVlVzLa5kxp9t+gb+AfWt4Ykh+eguTQSGnpecwVChuyW6BezkW1/iP
F5udkxgS6gaPk0DOoCsxiapSpwUKUW4DuUdf7GAXYRCJZCOZ1PVxdjMEjukEWE4v
bSF07LbF5Gy/5/8/rygEoxEgj/pVM5ARwPWHaPjUztLXxBnML22UHbN+kudZqLUH
MuDw1HxEJOE0SHLOWa5jbwAiO912tIaRP4CiVTyt0fsWekRhXbFUH2VbiLEeb77v
YI2DjpSG/NP/xJLz/gjADA8NAUHyEA==
=BNXr
-----END PGP SIGNATURE-----


J
J
Josselin Poiret wrote on 10 Jul 2023 09:13
(name . Athena Martin)(address . secure@alm.website)
87pm508cir.fsf@jpoiret.xyz
Hi Athena,

So it's not the LD_DEBUG output that hold a clue, but rather the Python
traceback.

Athena Martin <secure@alm.website> writes:

Toggle quote (12 lines)
> File "/gnu/store/dsgxdqs620pp284bfm1drbsjqpb36i4n-python-neovim-remote-2.5.1/bin/.nvr-real", line 4, in <module>
> import nvr.nvr as mod
> File "/home/alm/.local/lib/python3.10/site-packages/nvr/__init__.py", line 1, in <module>
> from .nvr import main
> File "/home/alm/.local/lib/python3.10/site-packages/nvr/nvr.py", line 34, in <module>
> import psutil
> File "/home/alm/.local/lib/python3.10/site-packages/psutil/__init__.py", line 102, in <module>
> from . import _pslinux as _psplatform
> File "/home/alm/.local/lib/python3.10/site-packages/psutil/_pslinux.py", line 26, in <module>
> from . import _psutil_linux as cext
> ImportError: libc.musl-x86_64.so.1: cannot open shared object file: No such file or directory

The nvr package in ~/.local seems to be used instead of a Guix package.
That locally installed nvr package expects to use the host's libc, but
since the python interpreter being used has a fixed RPATH and system
search path it won't find it.

.nvr-real should definitely be using the Python code inside the store, I
wonder why that isn't being done. Maybe our sitecustomize.py is
misbehaving? Can you do `guix shell python-neovim-remote python --
python3` then type `import sys.path; sys.path`?

Best,
--
Josselin Poiret
-----BEGIN PGP SIGNATURE-----

iQHEBAEBCgAuFiEEOSSM2EHGPMM23K8vUF5AuRYXGooFAmSrr5wQHGRldkBqcG9p
cmV0Lnh5egAKCRBQXkC5FhcaikcrDACPmPYBHbN4XnoSqHqBFEWKhDjnZEQMugsQ
OFhVJnAJAEhyGzg8Kj2/sEHayNC7L7nbMZZaw+ZiodUUaDhcvV151jZKJBQo64gp
75gZEu/xO1JHVobVi/at/0HuYxntnGhz5a02wtC3RwwPGCUDpx2XgfDVZwc116Eh
Tm9ClA9LGeLWbJJxXfi4O2v4uVlWoDBCWDAHXrN6P7uKTDJgZXDrEpuINuCjK1ra
hE/LFUYEPk6p7aS+EuttaXbBR3wHZgmX1d543idMlrkEwaarkGftKh4NxltlHYNa
BXU629CiMzP35BcXgvv9gU+28EO9qozA6XDXbrd9ShxwyvedCE8poV/5zkKxGYs/
gEF33wpMCsE7UTFRHIvfmEDxeCe/flgB8nxC/AKY30rFwYyYLTSVBoBvkCtEmxvH
kKORJ1Njvf1U61jUQUlaH5a9OyEy9BxoU92/ruYEPQHqMsuLjK83Abup2AfRna/H
7v8o3GzF4QfMzdCtNknEFwaiC6OWiXk=
=+jR5
-----END PGP SIGNATURE-----

A
A
Athena Martin wrote on 10 Jul 2023 21:47
(name . Josselin Poiret)(address . dev@jpoiret.xyz)
20230710154734.2b71b56b@spock.hosts.alm.website
Toggle quote (8 lines)
> So it's not the LD_DEBUG output that hold a clue, but rather the
> Python traceback.

> The nvr package in ~/.local seems to be used instead of a Guix
> package. That locally installed nvr package expects to use the host's
> libc, but since the python interpreter being used has a fixed RPATH
> and system search path it won't find it.

Ah, I see.

Toggle quote (6 lines)
> .nvr-real should definitely be using the Python code inside the
> store, I wonder why that isn't being done. Maybe our
> sitecustomize.py is misbehaving? Can you do `guix shell
> python-neovim-remote python -- python3` then type `import sys.path;
> sys.path`?

$ guix shell python-neovim-remote python -- python3
Toggle quote (1 lines)
>>> sys.path
['', '/gnu/store/dy3xh053ahkhrp2jamggq8cpsyvp8mg0-python-3.10.7/lib/python310.zip', '/gnu/store/dy3xh053ahkhrp2jamggq8cpsyvp8mg0-python-3.10.7/lib/python3.10', '/gnu/store/dy3xh053ahkhrp2jamggq8cpsyvp8mg0-python-3.10.7/lib/python3.10/lib-dynload', '/home/alm/.local/lib/python3.10/site-packages', '/gnu/store/ll75wx2cvm1dbbxjr095lcs1653q2zz1-profile/lib/python3.10/site-packages', '/gnu/store/dy3xh053ahkhrp2jamggq8cpsyvp8mg0-python-3.10.7/lib/python3.10/site-packages']

(It's not from the environment:)

$ guix shell python-neovim-remote python --pure -- python3
Toggle quote (1 lines)
>>> sys.path
['', '/gnu/store/dy3xh053ahkhrp2jamggq8cpsyvp8mg0-python-3.10.7/lib/python310.zip', '/gnu/store/dy3xh053ahkhrp2jamggq8cpsyvp8mg0-python-3.10.7/lib/python3.10', '/gnu/store/dy3xh053ahkhrp2jamggq8cpsyvp8mg0-python-3.10.7/lib/python3.10/lib-dynload', '/home/alm/.local/lib/python3.10/site-packages', '/gnu/store/ll75wx2cvm1dbbxjr095lcs1653q2zz1-profile/lib/python3.10/site-packages', '/gnu/store/dy3xh053ahkhrp2jamggq8cpsyvp8mg0-python-3.10.7/lib/python3.10/site-packages']
Toggle quote (1 lines)
>>> os.environ
environ({'HOME': '/home/alm', 'LOGNAME': 'alm', 'PAGER': 'less', 'DISPLAY': ':0', 'USER': 'alm', 'TERM': 'xterm-256color', 'PATH': '/gnu/store/ll75wx2cvm1dbbxjr095lcs1653q2zz1-profile/bin', 'GUIX_PYTHONPATH': '/gnu/store/ll75wx2cvm1dbbxjr095lcs1653q2zz1-profile/lib/python3.10/site-packages', 'GUIX_ENVIRONMENT': '/gnu/store/ll75wx2cvm1dbbxjr095lcs1653q2zz1-profile'})
-----BEGIN PGP SIGNATURE-----

iQEzBAEBCgAdFiEELAGoSzc6nHIdbhP+S8DcQuG8sXMFAmSsYFYACgkQS8DcQuG8
sXPssAf9EpHPxtQE5Z6rrhegm0NzQhRde1l10Ygdl6S1fEwv7nfi5sMc5HoZqmFJ
0bsPdV7zH28ja3HdTzwVGim4ZlwGQoU6JDzpJRzfb9mT6CYIwo/2/qHExWl233Vk
9AqPg+4Z08x2oYRDJ1l2+pPCJXs5Es58M/2cpj29Y7MIxgkUgPJGsKuwhev2Akd5
XqY4URLFWRUswFws4xFDwyr7I0wy00uNbWxZJVQU38F7rP3n4zT/+fuRNalDk2/A
53SU8E8vegFlY2zWbTxcOAhgitRvMtmFz1DEK1TqIBQIc+0s5xpktnhXN0p4uJbK
+itMeRwHilBS+GbJqXFL05z5HylJ6Q==
=kHyC
-----END PGP SIGNATURE-----


A
A
Athena Martin wrote on 10 Jul 2023 22:21
(name . Josselin Poiret)(address . dev@jpoiret.xyz)
20230710162122.190051b8@spock.hosts.alm.website
Toggle quote (5 lines)
> The nvr package in ~/.local seems to be used instead of a Guix
> package. That locally installed nvr package expects to use the
> host's libc, but since the python interpreter being used has a
> fixed RPATH and system search path it won't find it.

I've just checked and temporarily removing .local/lib/python3.10 makes
Guix's nvr work, and takes the .local site-packages off sys.path.
-----BEGIN PGP SIGNATURE-----

iQEzBAEBCgAdFiEELAGoSzc6nHIdbhP+S8DcQuG8sXMFAmSsaEIACgkQS8DcQuG8
sXP/uwgAvwU4yWcpnff4eX3I5rhCXgDEoOly3UMZpovPF26dqW9RpFQxgrJF5Aar
6+vGASglCZpSSvwbsDcUhNaL0oeWvXUvmiYrc70mmkR2j0TRLdI8PDD5q7tWr0CZ
rfiOL/i4GS0wso+qD0L4mEWPdDNe8Vx2ob2DDS3JS7VLKXAYo8wu/m5Bu9mVjf6n
SQ+/SVxAl9MDtFM2YzlAJnEMhjB7AfMtRFdrKxEtwURyjSZfAWm3QZqiuSUgbndP
c8CtP+YhD0gRMfRTfdQB07TyCF66Kl2zkairo0XkOh36s4DwlIZ1gN77GcedDY+I
35IOv6PxY0bqQ4IILukHTdpPAxkJMg==
=vq0j
-----END PGP SIGNATURE-----


J
J
Josselin Poiret wrote on 11 Jul 2023 10:34
(name . Athena Martin)(address . secure@alm.website)
87jzv6979d.fsf@jpoiret.xyz
Hi Athena,

Athena Martin <secure@alm.website> writes:

Toggle quote (12 lines)
> $ guix shell python-neovim-remote python -- python3
>>>> sys.path
> ['', '/gnu/store/dy3xh053ahkhrp2jamggq8cpsyvp8mg0-python-3.10.7/lib/python310.zip', '/gnu/store/dy3xh053ahkhrp2jamggq8cpsyvp8mg0-python-3.10.7/lib/python3.10', '/gnu/store/dy3xh053ahkhrp2jamggq8cpsyvp8mg0-python-3.10.7/lib/python3.10/lib-dynload', '/home/alm/.local/lib/python3.10/site-packages', '/gnu/store/ll75wx2cvm1dbbxjr095lcs1653q2zz1-profile/lib/python3.10/site-packages', '/gnu/store/dy3xh053ahkhrp2jamggq8cpsyvp8mg0-python-3.10.7/lib/python3.10/site-packages']
>
> (It's not from the environment:)
>
> $ guix shell python-neovim-remote python --pure -- python3
>>>> sys.path
> ['', '/gnu/store/dy3xh053ahkhrp2jamggq8cpsyvp8mg0-python-3.10.7/lib/python310.zip', '/gnu/store/dy3xh053ahkhrp2jamggq8cpsyvp8mg0-python-3.10.7/lib/python3.10', '/gnu/store/dy3xh053ahkhrp2jamggq8cpsyvp8mg0-python-3.10.7/lib/python3.10/lib-dynload', '/home/alm/.local/lib/python3.10/site-packages', '/gnu/store/ll75wx2cvm1dbbxjr095lcs1653q2zz1-profile/lib/python3.10/site-packages', '/gnu/store/dy3xh053ahkhrp2jamggq8cpsyvp8mg0-python-3.10.7/lib/python3.10/site-packages']
>>>> os.environ
> environ({'HOME': '/home/alm', 'LOGNAME': 'alm', 'PAGER': 'less', 'DISPLAY': ':0', 'USER': 'alm', 'TERM': 'xterm-256color', 'PATH': '/gnu/store/ll75wx2cvm1dbbxjr095lcs1653q2zz1-profile/bin', 'GUIX_PYTHONPATH': '/gnu/store/ll75wx2cvm1dbbxjr095lcs1653q2zz1-profile/lib/python3.10/site-packages', 'GUIX_ENVIRONMENT': '/gnu/store/ll75wx2cvm1dbbxjr095lcs1653q2zz1-profile'})

So, looks like the default Python behavior is to load the usercustomize
after the sitecustomize [1], which leads to exactly the behavior you're
experiencing. I don't know what we should do here, maybe pass `-s` to
the shebang line of Python to disable loading the usercustomize? That
would probably be a world-rebuild though. CC'ing the Python team to see
what they think.


Best,
--
Josselin Poiret
-----BEGIN PGP SIGNATURE-----

iQHEBAEBCgAuFiEEOSSM2EHGPMM23K8vUF5AuRYXGooFAmStE/4QHGRldkBqcG9p
cmV0Lnh5egAKCRBQXkC5FhcaiqpjC/0ZagMzkOIdrzOdVkZgbKqHvNaCtfwAvQpC
k//XUHp1VwIQG4wmyglL1Grch4DSGGZm6AWA1ERDklxiXt0vYLOEysXgRATr8wRS
uUbCXqdcjiIoXdHjRpKbHyDfpjbixUCe/pOwYIxyK98tD7OuduPkr/lkvArPWU7B
WJmvi7zXsNYHkTIGv01Cw5kjmX6e8ovBhuki8p0btMEX9S9WcSxmg/48fdBb0a72
471coPotpW3Xo5hYyq6JStA9G6hLxmJ47fbsYxhRQ1oE2sT6UHNd89kugHq1VCIZ
P6uObeYQJJ06TXwOlLGmgPcIuZiXu6MAKpv34nBI/htkIYHxkvYNn82Pik4dcnzs
ZVUa8R+TMy0pFHhcMd53lespyBIXN2VZjgWnD/TbvxEeQC5+jvGylXyb8V58g+BS
xq45OqDe/8R/fQ5/O1ahfQe2a3JOy4B8kgKKA8ozgJdzAsshb6RQSyAKofsIsCHM
0/UjS8HgOKzfY4XRId2gY9URTXUi4kw=
=Osvc
-----END PGP SIGNATURE-----

L
L
Lars-Dominik Braun wrote on 11 Jul 2023 14:43
(name . Josselin Poiret)(address . dev@jpoiret.xyz)
ZK1OeNPPIGHDZGpw@noor.fritz.box
Hi,

there’s a similar issue #63912 and a thread on the guix-devel
mailinglist at

Toggle quote (7 lines)
> So, looks like the default Python behavior is to load the usercustomize
> after the sitecustomize [1], which leads to exactly the behavior you're
> experiencing. I don't know what we should do here, maybe pass `-s` to
> the shebang line of Python to disable loading the usercustomize? That
> would probably be a world-rebuild though. CC'ing the Python team to see
> what they think.

I think the problem is bigger than usercustomize. Any custom PYTHONPATH
also slips through and causes this issue, as well as any custom
GUIX_PYTHONPATH, because the executable wrapper appends it (think nested
`guix shell` invokations with different versions of a library for
an example where this could go wrong).

Guix-managed Python packages (libraries nor applications) should
generally not pick up dependencies from random paths – only those
from their package description, so we can keep Guix’ promise of being
self-contained.

I have experimented with customizing Python’s importing mechanism
through a custom MetaPathFinder. It works by adding a __guix_pythonpath__
variable to every Python package’s __init__.py file and modifying the
module loader’s search path accordingly if such a variable exists. It
would provide exactly that guarantee, but it’s just a PoC at this
point – see attached file.

Apart from that I don’t see a good short-term solution right now. It’s
just how Python works.

Cheers,
Lars
# Credits to
# for the very good explanation of how Python’s import statement works.

import sys, os
from importlib.abc import MetaPathFinder
from importlib.machinery import SourceFileLoader, ModuleSpec, PathFinder

class GuixPythonFinder (MetaPathFinder):
def find_spec (self, fullname, path, target=None):
# Short-circuit for non-top-level imports, which already have a path.
if path:
return None

attrname = '__guix_pythonpath__'
searchPath = None
# Search for our caller.
frame = sys._getframe ()
while frame:
# If he has a search path, use it. This is mainly for executable
# scripts with `__name__ == '__main__'`.
searchPath = frame.f_globals.get (attrname, None)
if not searchPath:
# Otherwise check the top-level package for search paths
# declared in __init__.py
package = frame.f_globals.get ('__package__')
if package:
module = sys.modules.get (package)
if module:
searchPath = getattr (module, attrname, None)
if searchPath is not None:
break
frame = frame.f_back

# If we have a caller…
if searchPath is not None:
return PathFinder.find_spec (fullname, searchPath, target=target)
else:
# Otherwise we’re not responsible for this module.
return None

sys.meta_path.insert (0, GuixPythonFinder ())
J
J
Josselin Poiret wrote on 12 Jul 2023 10:50
(name . Lars-Dominik Braun)(address . lars@6xq.net)
87h6q98qe7.fsf@jpoiret.xyz
Hi Lars,

Lars-Dominik Braun <lars@6xq.net> writes:

Toggle quote (18 lines)
> I think the problem is bigger than usercustomize. Any custom PYTHONPATH
> also slips through and causes this issue, as well as any custom
> GUIX_PYTHONPATH, because the executable wrapper appends it (think nested
> `guix shell` invokations with different versions of a library for
> an example where this could go wrong).
>
> Guix-managed Python packages (libraries nor applications) should
> generally not pick up dependencies from random paths – only those
> from their package description, so we can keep Guix’ promise of being
> self-contained.
>
> I have experimented with customizing Python’s importing mechanism
> through a custom MetaPathFinder. It works by adding a __guix_pythonpath__
> variable to every Python package’s __init__.py file and modifying the
> module loader’s search path accordingly if such a variable exists. It
> would provide exactly that guarantee, but it’s just a PoC at this
> point – see attached file.

Woah, looks like a neat solution. Do you think it would scale for all
our Python packages without manual intervention? If so, this would
definitely be the way forward.

Toggle quote (3 lines)
> Apart from that I don’t see a good short-term solution right now. It’s
> just how Python works.

I mostly agree with you, but for this rather common case of having also
a usercustomize it would be nice to circumvent it. In general, I don't
think we ever want a Guix-produced Python script to load the
usercustomize, hence my suggestion. The other case of PYTHONPATH is
also annoying but can be tamed by modifying the env variable
temporarily.

Best,
--
Josselin Poiret
-----BEGIN PGP SIGNATURE-----

iQHEBAEBCgAuFiEEOSSM2EHGPMM23K8vUF5AuRYXGooFAmSuaWAQHGRldkBqcG9p
cmV0Lnh5egAKCRBQXkC5Fhcaima5C/9kdGYYe8WBijct1N4LtGgNAgtT7/BZ+O9H
CqDoBorRaM+QI2jTt6o2nPKAakVFcrDfLFH42xWcDs4KgB7wsZXphE/O3CuLpDgI
tUmxUrh2yd6HXY2NtjIqpGurHY0PGrUaEYgexB4f06cBVouoHkJve5ARgpH1ATbY
gQCvR4Txm5G41Zz4qLdFHtvB5jT9/pwaFvMrRvw/UQEEX/mGcirJyxxVwQGAU01C
BeBMi7W58MiGBYQpHX08123WrEvi5XPTFujkaxt0FIQs+LkDZGjsSqJFCme5vdme
WfYwu3ZLRXneXX4BJbALBG+0308Zi5rw/1Lyicy5DCjlP0T+JrwaItJYHTq3MoHS
69DiC1NYI6i398NHBkKm85umAhkX4fZTQgCZwW7FzLuoFvEijr1VBYUYLXupOGZG
LGY6JxFl3hqmp2RN2woxYafPMvKjOaJuvAiV6TZML1KPHPAhLoIoCSCckW2xNCUa
l/soAKw78GNyr+iWJKF+WKOuqCdOoG8=
=hgQZ
-----END PGP SIGNATURE-----

L
L
Lars-Dominik Braun wrote on 16 Jul 2023 10:35
(name . Josselin Poiret)(address . dev@jpoiret.xyz)
ZLOr5K4bTkZceqyS@noor.fritz.box
Hi Josselin,

Toggle quote (4 lines)
> Woah, looks like a neat solution. Do you think it would scale for all
> our Python packages without manual intervention? If so, this would
> definitely be the way forward.

I hope so, but haven’t tried it yet.

Toggle quote (7 lines)
> I mostly agree with you, but for this rather common case of having also
> a usercustomize it would be nice to circumvent it. In general, I don't
> think we ever want a Guix-produced Python script to load the
> usercustomize, hence my suggestion. The other case of PYTHONPATH is
> also annoying but can be tamed by modifying the env variable
> temporarily.

True, PYTHONPATH can be unset more easily than moving the user site
dir. I’ll have a look at #64573, which should work around this issue.

Cheers,
Lars
?
Your comment

Commenting via the web interface is currently disabled.

To comment on this conversation send an email to 64309@debbugs.gnu.org

To respond to this issue using the mumi CLI, first switch to it
mumi current 64309
Then, you may apply the latest patchset in this issue (with sign off)
mumi am -- -s
Or, compose a reply to this issue
mumi compose
Or, send patches to this issue
mumi send-email *.patch