You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
$ docker run --rm -ti --entrypoint sh python:2-alpine -c "python -c 'from ctypes.util import find_library;print(find_library(\"c\"))'"
None
so python:2-alpine seems to break something in addition to the general alpine issue, which renders even version 2 broken. Maybe the find_library issue could also be worked around by python image in general.
find_library relies on ldconfiggcc or objdump according to its document. gccobjdump need to be installed (by apk add gcc) separately as they are not included in the docker image, but won't work for some libraries, like libcairo. I've encountered this myself.
ldconfig seems broken according to the author of this bug, but the maintainer didn't say whether ldconfig is broken, instead he provided a patch addressing the issue.
Alpine image may need to apply the same patch to make find_library functional.
@ushuzldconfig works just fine. it does not cache anything like gnu libc does so there is nothing to print with ldconfig -p. as you understand they (rightfully) don't trust the ldconfig output parsing so the fall back to using gcc or objdump because the likely thought that there is no way there exist any system without those tools installed.
The patch we use in alpine is incomplete. The fundamental problem is when you try to dlopen libc itself, then bad things will happen. upstream musl libc has said they will fix but I don't know what the status is there.
We should probably report this to upstream python.
I'm a little confused here -- what's the use case for find_library('c') in the first place? It seems strange to me to be trying to dlopen libc itself in this way -- aren't most of the functions it provides already available through the Python standard library in some other way?
I'm a little confused here -- what's the use case for find_library('c') in the first place? It seems strange to me to be trying to dlopen libc itself in this way -- aren't most of the functions it provides already available through the Python standard library in some other way?
As mentioned in the SO link above, Twisted's inotify implementation uses find_library('c')
As noted above, ldconfig in Alpine is much simpler than it has to be for glibc
CPython's stdlib ctypes.util.find_library() depends on ldconfig -p or gccccobjdump or ldobjdump to work properly. But ldconfig -pgccccldobjdump are all missing from python:alpine images.
I think what's needed here is a patch that Python upstream would be willing to consider and/or merge themselves, and I haven't seen anyone propose anything like that (and there's been no response to my ping on the upstream bug several months ago).
I've submitted some PRs for cpython master, which should backport to 3.7 with minimal fuss considering there are no conflicts with the util.py file. python/cpython#10453
Also for the 2.7 branch python/cpython#10455
In the 3.7 branch, they have the ldconfig, gcc and objdump methods that reference the LD_LIBRARY_PATH to get names. I took the implementation above to walk that path referenced above and removed the alpine specific checks.
My opinion is that the decision for which library name is being sought should be maintained by the library/app based on the detection for the environment it is in or the user of the app/library to configure/override where applicable. Once you know which library name you want to find, and for the posix case, the LD_LIBRARY_PATH can determine where to search which is within the user's control and within the responsibility of the find_library function.
At least for my case, I can use the alpine:3.8 image, set ENV LD_LIBRARY_PATH in my Dockerfile, and make sure I apk add my run-time deps for anything my python apps may need to find using find_library. Logic for calling libc instead of libm, libcrypt, libpthread etc for example, I patch in my apps/libraries as they are the ones that need to be aware of which lib name to search for, then they can rely on the python to find it. Duplicated software for cases like that, yes, but find_library actually does what it sets out to do. Finds a library by the name I give it.
Reacted by John HU, Cyril Jouve and Florijan Hamzic
Last time I looked at / considered python/cpython#18380, it appeared to be more fundamentally controversial than it is now, so this is indeed probably something we should seriously consider applying and keeping up with (especially given that per PEP 11, Alpine/musl is not a supported platform, so it seems reasonable for us to consider carrying this patch unless/until that's resolved).
Yes, but the biggest challenge (that I don't have a simple answer to atm) is going to be finding a clean way to maintain the patch, especially with the necessary changes for different Python versions. Ideally we'd just download it directly from a URL like https://github.com/python/cpython/pull/18380.diff?full_index=1 and validate it with a sha256 (currently bedc83b96b4888bf6540178719ab120a69e61f061dd54c2b00e3a6918f534bf3), accepting that we'll need to manually update that any time the PR has changes, but my own testing shows that's not actually tenable (patch currently doesn't apply as-is on at least Python 3.12, and that URL appears to be subject to more strict rate limits than other GitHub URLs).
Something like a hacky "sed the right source files" type construction is out of the question, and I'd really like to avoid maintaining patch files in this repository directly, so this needs some more thought on approaches for getting/maintaining patches across all supported Python versions before we can commit to it fully.
Activity
ushuz commentedon Jun 30, 2016
find_libraryrelies onldconfiggccorobjdumpaccording to its document.gccobjdumpneed to be installed (byapk add gcc) separately as they are not included in the docker image, but won't work for some libraries, likelibcairo. I've encountered this myself.ldconfigseems broken according to the author of this bug, but the maintainer didn't say whetherldconfigis broken, instead he provided a patch addressing the issue.Alpine image may need to apply the same patch to make
find_libraryfunctional.@yosifkit @tianon @ncopa
ncopa commentedon Jun 30, 2016
@ushuz
ldconfigworks just fine. it does not cache anything like gnu libc does so there is nothing to print withldconfig -p. as you understand they (rightfully) don't trust the ldconfig output parsing so the fall back to usinggccorobjdumpbecause the likely thought that there is no way there exist any system without those tools installed.The patch we use in alpine is incomplete. The fundamental problem is when you try to dlopen libc itself, then bad things will happen. upstream musl libc has said they will fix but I don't know what the status is there.
We should probably report this to upstream python.
ushuz commentedon Jun 30, 2016
@ncopa But why calling
ldconfig -ponalpine:latestoutputsIllegal option -p?danielfaust commentedon Jan 13, 2018
Twisted server: monkey-patch file
Running Twisted (Python 2.7.x) on Alpine Linux 3.7 inside Docker.
https://stackoverflow.com/q/48234723/277267
tianon commentedon Jun 8, 2018
I'm a little confused here -- what's the use case for
find_library('c')in the first place? It seems strange to me to be trying todlopenlibc itself in this way -- aren't most of the functions it provides already available through the Python standard library in some other way?tianon commentedon Jun 8, 2018
As noted above,
ldconfigin Alpine is much simpler than it has to be for glibc; here's the entire script contents of/sbin/ldconfigin Alpine:ushuz commentedon Jun 9, 2018
@tianon
As mentioned in the SO link above, Twisted's inotify implementation uses
find_library('c')https://github.com/twisted/twisted/blob/6ac66416c0238f403a8dc1d42924fb3ba2a2a686/src/twisted/python/_inotify.py#L106-L110
CPython's stdlib
ctypes.util.find_library()depends onldconfig -porgccccobjdumporldobjdumpto work properly. Butldconfig -pgccccldobjdumpare all missing frompython:alpineimages.https://github.com/python/cpython/blob/4acc140f8d2c905197362d0ffec545a412ab32a7/Lib/ctypes/util.py#L255-L312
So I tried installing
gcc, but the result seems odd.jouve commentedon Jul 5, 2018
alpine maintainers apply the following patch : https://github.com/alpinelinux/aports/blob/master/main/python2/musl-find_library.patch
can you put the same in the image ?
tianon commentedon Jul 16, 2018
Did anyone end up doing so? (not seeing a link anywhere in the comments here)
They definitely won't fix it if they don't know it's an issue. 😅
tianon commentedon Jul 16, 2018
It looks like https://bugs.python.org/issue21622 is probably the right place.
tianon commentedon Oct 2, 2018
To clarify, this is definitely an issue, and definitely something that ought to be fixed, but I'm not keen on the implementation in https://github.com/alpinelinux/aports/blob/202f4bea916b0cf974b38ced96ab8fca0b192e3f/main/python2/musl-find_library.patch especially given that it's very Alpine-specific and doesn't appear to have had any review by the Python maintainers (which I'd want for something that patches the standard library).
I think what's needed here is a patch that Python upstream would be willing to consider and/or merge themselves, and I haven't seen anyone propose anything like that (and there's been no response to my ping on the upstream bug several months ago).
jcastillo2nd commentedon Nov 10, 2018
I've submitted some PRs for cpython master, which should backport to 3.7 with minimal fuss considering there are no conflicts with the util.py file.
python/cpython#10453
Also for the 2.7 branch
python/cpython#10455
In the 3.7 branch, they have the ldconfig, gcc and objdump methods that reference the LD_LIBRARY_PATH to get names. I took the implementation above to walk that path referenced above and removed the alpine specific checks.
My opinion is that the decision for which library name is being sought should be maintained by the library/app based on the detection for the environment it is in or the user of the app/library to configure/override where applicable. Once you know which library name you want to find, and for the posix case, the LD_LIBRARY_PATH can determine where to search which is within the user's control and within the responsibility of the find_library function.
At least for my case, I can use the alpine:3.8 image, set
ENV LD_LIBRARY_PATHin my Dockerfile, and make sure Iapk addmy run-time deps for anything my python apps may need to find using find_library. Logic for calling libc instead of libm, libcrypt, libpthread etc for example, I patch in my apps/libraries as they are the ones that need to be aware of which lib name to search for, then they can rely on the python to find it. Duplicated software for cases like that, yes, but find_library actually does what it sets out to do. Finds a library by the name I give it.tianon commentedon Apr 5, 2021
Closing in favor of the upstream tracking issue (https://bugs.python.org/issue21622), since this is really an upstream bug. 😅 ❤️
onedr0p commentedon Apr 15, 2025
In the meantime why can't a patch be made for Alpine specifically? E.g. something like below?
https://github.com/home-assistant/docker-base/blob/ddc5dbcce5de4c91d46f34f4f4e2d3ff57228bcb/python/3.13/musl-find_library.patch
It would help a lot since people wouldn't need to build Python themselves or write a script to symlink libraries to a
.so$tianon commentedon Apr 21, 2025
Last time I looked at / considered python/cpython#18380, it appeared to be more fundamentally controversial than it is now, so this is indeed probably something we should seriously consider applying and keeping up with (especially given that per PEP 11, Alpine/musl is not a supported platform, so it seems reasonable for us to consider carrying this patch unless/until that's resolved).
onedr0p commentedon Apr 21, 2025
@tianon that would be fantastic and thank you for reopening, it's one of those gotchas that people run into and spend hours debugging.
onedr0p commentedon May 6, 2025
@tianon would you be open to PRs to add this functionality across all the Python versions? I may have some free time to help out.
tianon commentedon May 6, 2025
Yes, but the biggest challenge (that I don't have a simple answer to atm) is going to be finding a clean way to maintain the patch, especially with the necessary changes for different Python versions. Ideally we'd just download it directly from a URL like
https://github.com/python/cpython/pull/18380.diff?full_index=1and validate it with a sha256 (currentlybedc83b96b4888bf6540178719ab120a69e61f061dd54c2b00e3a6918f534bf3), accepting that we'll need to manually update that any time the PR has changes, but my own testing shows that's not actually tenable (patch currently doesn't apply as-is on at least Python 3.12, and that URL appears to be subject to more strict rate limits than other GitHub URLs).Something like a hacky "
sedthe right source files" type construction is out of the question, and I'd really like to avoid maintaining patch files in this repository directly, so this needs some more thought on approaches for getting/maintaining patches across all supported Python versions before we can commit to it fully.