Repository navigation
Python 3.12+ breaks backwards compatibility for logging QueueHandler with queue.SimpleQueue #124653
Copy link
Copy link
Closed
Labels
stdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directorytype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
Description
Bug report
Bug description:
I think this is related to #119819
import logging.config
from queue import SimpleQueue
q = SimpleQueue()
config = {
'version': 1,
'handlers': {
'sink': {
'class': 'logging.handlers.QueueHandler',
'queue': q,
},
},
'root': {
'handlers': ['sink'],
},
}
logging.config.dictConfig(config)ValueError: Unable to configure handler 'sink'
SimpleQueue does not implement the full Queue interfaces thus both isinstance(obj, queue.Queue) and the queue interface check fails.
Since this has been working on 3.8 - <3.12 I think the queue interface check is checking for methods that are not used at all and should be adjusted accordingly.
Lines 500 to 525 in 2518918
| def _is_queue_like_object(obj): | |
| """Check that *obj* implements the Queue API.""" | |
| if isinstance(obj, queue.Queue): | |
| return True | |
| # defer importing multiprocessing as much as possible | |
| from multiprocessing.queues import Queue as MPQueue | |
| if isinstance(obj, MPQueue): | |
| return True | |
| # Depending on the multiprocessing start context, we cannot create | |
| # a multiprocessing.managers.BaseManager instance 'mm' to get the | |
| # runtime type of mm.Queue() or mm.JoinableQueue() (see gh-119819). | |
| # | |
| # Since we only need an object implementing the Queue API, we only | |
| # do a protocol check, but we do not use typing.runtime_checkable() | |
| # and typing.Protocol to reduce import time (see gh-121723). | |
| # | |
| # Ideally, we would have wanted to simply use strict type checking | |
| # instead of a protocol-based type checking since the latter does | |
| # not check the method signatures. | |
| queue_interface = [ | |
| 'empty', 'full', 'get', 'get_nowait', | |
| 'put', 'put_nowait', 'join', 'qsize', | |
| 'task_done', | |
| ] | |
| return all(callable(getattr(obj, method, None)) | |
| for method in queue_interface) |
Tested with 3.12.6
CPython versions tested on:
3.12
Operating systems tested on:
Windows
Linked PRs
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
stdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directorytype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
Projects
- StatusShow more project fieldsDone
Activity
YvesDup commentedon Oct 1, 2024
Except if I miss something,
SimpleQueuehas never had aput_nowaitmethod, the one used in theQueueHandlerandQueueListenerclasses (Just see here) . So using this class in the loggingQueueHandleralways failed.spacemanspiff2007 commentedon Oct 1, 2024
As I've written this has been working on 3.8 - 3.11. I'm not sure exactly when it broke.
SimpleQueueactually implements put_nowait.I skimmed over the file you linked and it seems the only required interface methods are
put_nowaitandget.The interface check should reflect that.
Additionally
gethas to raisequeue.Emptyif the queue is empty but there is no way to check that ...YvesDup commentedon Oct 1, 2024
My apologies for my mistaken: I was thinking you talked about
multiprocessing.SimpleQueuenot aboutqueue.SimpleQueue. So first of all, I suggess to modify title issue (prefixingSimpleQueuewith thequeuemodule).And then, I agree with you the
queue_interfacelist of the_is_queue_like_objectmethod is too restrictive. At leastjoinandtask_donemethods must be removed.fullandemptymethods (or exceptions) have to exam too.Perhars it will be nice to ask for a python core dev advice.
[-]Python 3.12+ breaks backwards compatibility for logging QueueHandler with SimpleQueue[/-][+]Python 3.12+ breaks backwards compatibility for logging QueueHandler with queue.SimpleQueue[/+]YvesDup commentedon Oct 2, 2024
@picnixz as GH-122154 author, and introducing
is_queue_like_objectin filelogging/config.py, could you take a look to this issue please ?picnixz commentedon Oct 2, 2024
Urgh, this issue will haunt me all my life :') According to the docs, it required a "Queue API", but I didn't consider that SimpleQueue was... too simple enough and did not entirely conform to what Queue did. Ok, So I think we should only care about two methods that are those given in SimpleQueue.
YvesDup commentedon Oct 2, 2024
What do you think about adding
queue.simpleQueueat L502, as below:picnixz commentedon Oct 2, 2024
It's correct (and that's what I also did), but since we really don't know whether people could use objects or not I just relaxed the interface (and I think it's fine like this).
YvesDup commentedon Oct 2, 2024
@spacemanspiff2007 good catch !!
spacemanspiff2007 commentedon Oct 2, 2024
@YvesDup @picnixz Thank you both for your help and implementation
picnixz commentedon Oct 2, 2024
I should be the one thanking you since this was my code :') sorry for the inconvenience!
gh-124653: Relax (again) detection of queue API for logging handlers (G…
pythongh-124653: Relax (again) detection of queue API for logging han…
pythongh-124653: Relax (again) detection of queue API for logging han…
[3.13] gh-124653: Relax (again) detection of queue API for logging ha…
[3.12] gh-124653: Relax (again) detection of queue API for logging ha…