-
Notifications
You must be signed in to change notification settings - Fork 58
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow underlying queue to be customized #40
base: master
Are you sure you want to change the base?
Conversation
Interesting. What is the use case for this? |
So, like I said, the core use case is being able to use a custom queue. The long story is that I'm using some CUDA code with multiprocessing (and hopefully logging too!). CUDA will not work with the default (on Unix based systems) I've written some fairly repository specific code to allow me to do logging from multiprocessing with a So, in the end, I'd really like to take advantage of the |
This is very interesting! Lets me read a little and play a little with this. |
Yeah, in a perfect world, I agree. Unfortunately, to get logging to work in my class QueueProxy():
"""
Exposes a multiprocessing.Queue interface to a queue.Queue
"""
def __init__(self, q):
self.q = q
def qsize(self):
return self.q.qsize()
def empty(self):
return self.q.empty()
def full(self):
return self.q.full()
def put(self, *args, **kwargs):
return self.q.put(*args, **kwargs)
def put_nowait(self, *args, **kwargs):
return self.q.put_nowait(*args, **kwargs)
def get(self, *args, **kwargs):
return self.q.get(*args, **kwargs)
def get_nowarit(self, *args, **kwargs):
return self.q.get_nowait(*args, **kwargs)
def close(self):
pass
def join_thread(self):
pass
def cancel_join_thread(self):
pass
class ManagedQueueMultiProcessingHandler(MultiProcessingHandler):
def __init__(self, name, sub_handler=None):
super().__init__(name, sub_handler, lambda: QueueProxy(multiprocessing.Manager().Queue(-1)))
def _initwrap(queues, levels, initfunc, initargs):
# Configure the logger for this process
root_logger = logging.getLogger("")
for handler in root_logger.handlers:
root_logger.removeHandler(handler)
root_logger.setLevel(0)
for queue, level in zip(queues, levels):
handler = logging.handlers.QueueHandler(queue)
handler.setLevel(level)
root_logger.addHandler(handler)
# Call the original provided initfunc
if initfunc is not None and initargs is not None:
initfunc(*initargs)
elif initfunc is not None:
initfunc()
class LoggedSpawnerPool(multiprocessing.pool.Pool):
def __init__(self, processes=None, initializer=None, initargs=None, maxtasksperchild=None, context=None):
queues = []
levels = []
for handler in logger.parent.handlers:
if isinstance(handler, MultiProcessingHandler):
queues.append(handler.queue)
levels.append(handler.level)
else:
logger.warn(f"Log handler {handler} is not a MultiProcessingHandler, so will not get log messages during multiprocessing")
ctx = multiprocessing.get_context("spawn") if context is None else context
super().__init__(processes, _initwrap, [queues, levels, initializer, initargs], maxtasksperchild, ctx) which can then be used like logger = logging.getLogger(__name__)
def worker(args):
x = args
logger.info(x)
if __name__ == "__main__":
config_logging() # sets handlers and wraps them in ManagedQueueMulitProcessingHandler
with LoggedSpawnerPool(3) as pool:
pool.map(worker, range(10)) Hopefully that can help give you a little more context. |
def __init__(self, name, sub_handler=None, queue_factory=None): | ||
""" | ||
:param name: The name of this handler | ||
:param sub_handler: The handler to foward events to. If None, use a new logging.SteamHandler |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
:param sub_handler: The handler to foward events to. If None, use a new logging.SteamHandler | |
:param sub_handler: The handler to forward events to. If None, use a new logging.SteamHandler |
I've got a use case where I have I'd like to inject a custom queue type that behaves closely to multiprocessing.Queue. This allows the user to supply a factory function to create new queue instances.