Welcome!
This is the community forum for my apps Pythonista and Editorial.
For individual support questions, you can also send an email. If you have a very short question or just want to say hello — I'm @olemoritz on Twitter.
ctypes.pythonapi not usable?
-
@omz Following code raises an
AttributeError
in Pythonista:import ctypes print ctypes.pythonapi.PyThreadState_SetAsyncExc
In Pythonista, the error is
AttributeError: dlsym(RTLD_DEFAULT, PyThreadState_SetAsyncExc): symbol not found
.But it works with PC version Python and the correct output should be something
<_FuncPtr object at 0x10223be20>
I looked into
__init__.py
of the ctypes module and found following codeif _os.name in ("nt", "ce"): pythonapi = PyDLL("python dll", None, _sys.dllhandle) elif _sys.platform == "cygwin": pythonapi = PyDLL("libpython%d.%d.dll" % _sys.version_info[:2]) else: pythonapi = PyDLL(None)
Apparently, the
else
clause should take effect. Since the Pythonista environment is quite special, are there some settings missing in the DLL initialisation? I triedPyDLL('libpythonista.a')
but got errorimage not found
.Any tips?
-
Strange, this prints something like
<_FuncPtr object at 0x106ab31c8>
for me:import ctypes print ctypes.pythonapi.PyThreadState_SetAsyncExc
-
@omz My device is an iPad Air 2 WiFi 64GB. I do also have an iPhone5 which I believe is a 32-bit device. But you are on 64-bit as well, right?
I am also on the latest Beta (160023).
Here is the full Trackback:
Traceback (most recent call last): File "<string>", line 1, in <module> File "/private/var/mobile/Containers/Bundle/Application/650B1932-78AB-40BF-80BC-9BE928D8090B/Pythonista.app/pylib/ctypes/__init__.py", line 378, in __getattr__ func = self.__getitem__(name) File "/private/var/mobile/Containers/Bundle/Application/650B1932-78AB-40BF-80BC-9BE928D8090B/Pythonista.app/pylib/ctypes/__init__.py", line 383, in __getitem__ func = self._FuncPtr((name_or_ordinal, self)) AttributeError: dlsym(RTLD_DEFAULT, PyThreadState_SetAsyncExc): symbol not found
-
I guess it might have to do with me running a debug build... Could you try a different function in
pythonapi
, something likePyObject_Str
? There's this note in the docs aboutPyThreadState_SetAsyncExc
, so I think it might be "special" somehow:To prevent naive misuse, you must write your own C extension to call this.
-
No luck. Still the same error with
PyObject_Str
... -
The most likely explanation seems to be that debug symbols are stripped from release builds (TestFlight betas are built with the "release" configuration), but not from debug builds that I deploy directly from Xcode on my device... (which is probably why it works for me). I'm installing the TestFlight build right now to verify this.
I'm not sure if I want to turn off symbol stripping just to make the Python C API accessible. I honestly don't see a lot of practical use cases for this, and it might have a negative impact on size and performance of the binary.
-
Okay, I can verify that this doesn't work in the TestFlight build.
-
I am no expert on iOS app building process. But I don't quite understand why you have to enable the entire debug builds just for exposing the Python C API.
The PC version Python is definitely not released as debug builds, yet it still allow access to the C API. I would guess there is something minor that could be changed in build settings to allow the C API becoming available. Maybe it is just a matter of including a DLL file. On OS X, I am able to load the C Library by calling
print ctypes.PyDLL('libpython2.7.dylib').PyThreadState_SetAsyncExc
. -
@omz
I wonder whether this could be a **permission ** issue which prevents the library file being loaded byPyDLL
?In 1.5, we can access the
Pythonista.app
folder alongside with theDocuments
folder. But it is no longer there in 1.6. Presumably this folder is where the library file (e.g.libpython.dylib
) resides. Is this something worth to look at? Again I am no expert and could be very wrong. Please bear with me.My intention is to use this API for better thread management in StaSh so that a worker thread can be interupted/stopped by user from the UI thread.