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
asyncio.get_event_loop() DeprecationWarning in Python 3.12 #255
/.venv/lib/python3.12/site-packages/evdev/eventio_async.py:101: DeprecationWarning: There is no current event loop
loop = asyncio.get_event_loop()
asyncio.get_event_loop() produces a DeprecationWarning when called (see above for an example), and there are a couple of instances of get_event_loop being used in this package.
When called from a coroutine or a callback (e.g. scheduled with call_soon or similar API), this function will always return the running event loop.
If there is no running event loop set, the function will return the result of the get_event_loop_policy().get_event_loop() call.
Because this function has rather complex behavior (especially when custom event loop policies are in use), using the get_running_loop() function is preferred to get_event_loop() in coroutines and callbacks.
The get_event_loop() behavior is changing and the documentation says to use get_running_loop(), so that would be the good practice. get_event_loop() will eventually (supposedly in Python 3.16) do nothing but return a running/explicitly-set loop, never create one. Since python-evdev depends on the implicit-creation behavior, it will break.
This code will reproduce the deprecation warning on Python 3.12 and 3.13:
"""Reproduce the evdev DeprecationWarningRun against published evdev (which still has the get_event_loop() call): uv run --python 3.12 --with evdev python repro_evdev_real.pyOpens a real input device and closes it with no running/current event loop --the normal lifecycle of an InputDevice in a synchronous program. close() reachesevdev/eventio_async.py: `loop = asyncio.get_event_loop()`, which warns on 3.12/3.13."""importsysimportwarningswarnings.simplefilter("always") # don't dedupe/suppress DeprecationWarningfromimportlib.metadataimportversionimportevdevprint(f"Python {sys.version.split()[0]}, evdev {version('evdev')}")
# Find a device we can actually open (we're in the `input` group).dev=Noneforpathinevdev.list_devices():
try:
dev=evdev.InputDevice(path)
breakexceptPermissionError:
continueifdevisNone:
sys.exit("no openable /dev/input/event* device found")
print(f"opened {dev.path} ({dev.name!r})")
dev.close() # <-- get_event_loop() warning fires hereprint("closed")
In my code, I'm not using any of the async EventIO methods, but the async class is the one that's created. So that's why I get the warning on close.
Thanks, in your snipped I do get the warning. I previously started my own application in a hurry to see if the log appears there, I probably create a loop somewhere in there myself.
If there is no running event loop set, the function will return the result of the get_event_loop_policy().get_event_loop() call.
get_event_loop() will eventually (supposedly in Python 3.16) do nothing but return a running/explicitly-set loop, never create one
Mean that get_event_loop creates a new event loop? I'll need to look more into this, but I'm kinda busy. If you know the answer already, I'll appreciate your help. I think it's kinda confusing, since the method to create a new loop is called new_event_loop, so I'd expect different behavior from policy.get_event_loop. Maybe this is part of the reason for the deprecations?
I honestly haven't really worked with asyncio in quite a while. I'll need to understand this to make sure we aren't pushing a breaking change.
I'll then run input-remappers tests with the change with various python versions, as python-evdev doesn't have lots of tests.
If there is no running event loop set, the function will return the result of the get_event_loop_policy().get_event_loop() call.
get_event_loop() will eventually (supposedly in Python 3.16) do nothing but return a running/explicitly-set loop, never create one
Mean that get_event_loop creates a new event loop?
If there isn't a running loop, it will create one. If there is already a running loop, it uses that.
I think it's kinda confusing, since the method to create a new loop is called new_event_loop, so I'd expect different behavior from policy.get_event_loop. Maybe this is part of the reason for the deprecations?
Yes, I think so. It does seem confusing.
I think the way most people probably use the async EventIO class (including the way the code in the Tutorial works), they will already have a loop, so switching the underlying code over to get_running_loop shouldn't break them. There is a possibility that they're using the class to create a loop though, so it wouldn't be equivalent code.
I don't think this is urgent, I just think it does need to get addressed since Python doesn't want code to use get_event_loop, and the DeprecationWarning is an indication of that. As I noted above, I actually use the synchronous class calls in my application, so I don't have a natural testbed for this. But I am happy to write something up for review. It may be a few weeks until I can do that.
Let me know what you think of that PR. If it's acceptable, I can move it out of draft. I can also include my testing scripts and test results if you'd like. I don't see any information on contributing to this repo, but if I've missed something, let me know.
Activity
sezanzeb commentedon Jun 17, 2026
Hm, I'm not getting a deprecation warning in python 3.13.7
I can't say what asyncio good practices are, but I suppose you'd usually set your event loop before using python-evdev.
ekenyon676 commentedon Jun 17, 2026
According to the documentation:
The
get_event_loop()behavior is changing and the documentation says to useget_running_loop(), so that would be the good practice.get_event_loop()will eventually (supposedly in Python 3.16) do nothing but return a running/explicitly-set loop, never create one. Since python-evdev depends on the implicit-creation behavior, it will break.This code will reproduce the deprecation warning on Python 3.12 and 3.13:
In my code, I'm not using any of the async
EventIOmethods, but the async class is the one that's created. So that's why I get the warning on close.sezanzeb commentedon Jun 17, 2026
Thanks, in your snipped I do get the warning. I previously started my own application in a hurry to see if the log appears there, I probably create a loop somewhere in there myself.
For future reference, here is the deprecation documented: https://docs.python.org/3/library/asyncio-policy.html#asyncio.DefaultEventLoopPolicy
So both methods will raise the error from 3.14 on
And the docs say, that from 3.16 on, policies will be removed https://docs.python.org/3/library/asyncio-policy.html#policies
i never worked with policies though. How is get_event_loop_policy().get_event_loop() different from asyncio.get_event_loop()?
sezanzeb commentedon Jun 17, 2026
Does
Mean that get_event_loop creates a new event loop? I'll need to look more into this, but I'm kinda busy. If you know the answer already, I'll appreciate your help. I think it's kinda confusing, since the method to create a new loop is called new_event_loop, so I'd expect different behavior from policy.get_event_loop. Maybe this is part of the reason for the deprecations?
I honestly haven't really worked with asyncio in quite a while. I'll need to understand this to make sure we aren't pushing a breaking change.
I'll then run input-remappers tests with the change with various python versions, as python-evdev doesn't have lots of tests.
ekenyon676 commentedon Jun 18, 2026
If there isn't a running loop, it will create one. If there is already a running loop, it uses that.
Yes, I think so. It does seem confusing.
I think the way most people probably use the async EventIO class (including the way the code in the Tutorial works), they will already have a loop, so switching the underlying code over to
get_running_loopshouldn't break them. There is a possibility that they're using the class to create a loop though, so it wouldn't be equivalent code.I don't think this is urgent, I just think it does need to get addressed since Python doesn't want code to use
get_event_loop, and the DeprecationWarning is an indication of that. As I noted above, I actually use the synchronous class calls in my application, so I don't have a natural testbed for this. But I am happy to write something up for review. It may be a few weeks until I can do that.sezanzeb commentedon Jul 9, 2026
#258 that's it, right?
ekenyon676 commentedon Jul 13, 2026
I was thinking you'd want something more like #259.
ekenyon676 commentedon Jul 15, 2026
Let me know what you think of that PR. If it's acceptable, I can move it out of draft. I can also include my testing scripts and test results if you'd like. I don't see any information on contributing to this repo, but if I've missed something, let me know.
ekenyon676 commentedon Aug 19, 2026
Thanks for taking the PR a few weeks ago. Do you have an ETA on a release? Thank you!
gvalkov commentedon Aug 25, 2026
Hi @ekenyon676 . evdev 2.0.0 was released on Aug 23, 2026.