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
{{ message }}
Repository navigation
raise AttributeError if loading fails in ctypes.LibraryLoader.__getattr__ #78997
ctypes.windll is an instance of ctypes.LibraryLoader, which has a __getattr__ method that calls ctypes.WinDLL(name) and caches the result as an instance attribute. I suppose with chained exceptions it's reasonable to handle OSError in __getattr__ by raising AttributeError. For example:
>>> b = B()
>>> b.test
Traceback (most recent call last):
File "<stdin>", line 4, in __getattr__
File "<stdin>", line 3, in __init__
OSError
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 6, in __getattr__
AttributeError
>>> hasattr(b, 'test')
False
FYI, I recommend avoiding the cdll and windll LibraryLoader instances. I wish they were deprecated because globally caching CDLL and WinDLL instances leads to conflicts between projects that use the same shared libraries.
I am not sure if I understood correctly:
Do you suggest to modify ctypes.__init__.py so that the __getattr__ method of LibraryLoader catches the OSError and raises an AttributeError instead, as in your example?
For the record, why was a backwards incompatible change made in just a point release without any deprecation warnings? We can work around this change from throwing OSError to AttrbteError in cdll but why on earth was this change added in a minor release?
This change was really communicated badly in the windows section of the changelog:
[bpo-34816](https://bugs.python.org/issue?@action=redirect&bpo=34816): hasattr(ctypes.windll, 'nonexistant') now returns False instead of raising [OSError](https://docs.python.org/3/library/exceptions.html#OSError).
Activity
lfriedri commentedon Sep 27, 2018
The following creates an OSError:
The expected behavior would be to return "False"
eryksun commentedon Sep 27, 2018
ctypes.windll is an instance of ctypes.LibraryLoader, which has a __getattr__ method that calls ctypes.WinDLL(name) and caches the result as an instance attribute. I suppose with chained exceptions it's reasonable to handle OSError in __getattr__ by raising AttributeError. For example:
Demo:
>>> b = B() >>> b.test Traceback (most recent call last): File "<stdin>", line 4, in __getattr__ File "<stdin>", line 3, in __init__ OSError During handling of the above exception, another exception occurred: Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 6, in __getattr__ AttributeError >>> hasattr(b, 'test') FalseFYI, I recommend avoiding the cdll and windll LibraryLoader instances. I wish they were deprecated because globally caching CDLL and WinDLL instances leads to conflicts between projects that use the same shared libraries.
lfriedri commentedon Sep 27, 2018
Thank you for your reply.
I am not sure if I understood correctly:
Do you suggest to modify ctypes.__init__.py so that the __getattr__ method of LibraryLoader catches the OSError and raises an AttributeError instead, as in your example?
eryksun commentedon Mar 28, 2021
Yes. It seems no one was keen to work on this. I think it's relatively easy, so I'll add that flag in case someone is looking for an easy issue.
[-]ctypes + hasattr[/-][+]raise AttributeError if loading fails in ctypes.LibraryLoader.__getattr__[/+]farfella commentedon Apr 4, 2021
First patch fixing only the issue at hand on master. LibraryLoader now catches OSError for FileNotFoundError and raises AttributeError.
gh-78997: AttributeError if loading fails in LibraryLoader.__getattr__
Merge branch 'main' into fastmock
gh-78997: fix bad rebase of moved test file (#100424)
Merged main into regmachine branch (#50)
hauntsaninja commentedon Jan 29, 2023
Thanks, looks like this was fixed!
kevinhendricks commentedon Feb 28, 2024
For the record, why was a backwards incompatible change made in just a point release without any deprecation warnings? We can work around this change from throwing OSError to AttrbteError in cdll but why on earth was this change added in a minor release?
fzimmermann89 commentedon Jun 25, 2025
This change was really communicated badly in the windows section of the changelog: