-
-
Notifications
You must be signed in to change notification settings - Fork 30.9k
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
Creating multiprocessing.Queues
operates strangely with Process
's created in classes
#123208
Comments
multiprocessing.Queues
have weird behaviors when used with classes and `Process'smultiprocessing.Queues
operates strangely with `Process's
multiprocessing.Queues
operates strangely with `Process'smultiprocessing.Queues
operates strangely with Process
's created in classes
Note that if I give two queues (for the put get init) and only put get for one of them, the second works just fine |
This comment was marked as resolved.
This comment was marked as resolved.
This problem exists. I can reproduce it on MacOS. I think this is a spawn mode only problem. maybe you can try Would you mind to assign this issue to me? cc @picnixz |
I can reproduce it in |
I am wondering if the |
@YvesDup The last two of the original examples show that it has to do with the Queue being created in a class creating a process. All three of the following break: from multiprocessing import Process, Queue
from time import sleep
def foo(q) -> None:
pass
class Bar:
def __init__(self) -> None:
pass
def method(self):
self.q = Queue()
p = Process(target=foo, args=(self.q,))
p.start()
if __name__ == '__main__':
Bar().method()
sleep(1) from multiprocessing import Process, Queue
from time import sleep
def foo(q) -> None:
pass
class Bar:
def __init__(self) -> None:
self.q = Queue()
self.method()
def method(self):
p = Process(target=foo, args=(self.q,))
p.start()
if __name__ == '__main__':
Bar()
sleep(1) from multiprocessing import Process, Queue
from time import sleep
def foo(q) -> None:
pass
class Bar:
def __init__(self) -> None:
self.method()
def method(self):
self.q = Queue()
p = Process(target=foo, args=(self.q,))
p.start()
if __name__ == '__main__':
Bar()
sleep(1) |
After diving into this problem, I think it's not a bug. The issue is caused by the TL;DR; For now, the
The default mode on macOS is spawn mode which is much slower than I think maybe we need to update the documentation to add more tips? |
@Zheaoli I have found some interesting behavior and I think I understand what is happening: garbage collection. Let's keep class Foo:
def __init__(self, q) -> None:
pass Now, let's take a look at In this example, the script has no issues: class Bar:
def __init__(self) -> None:
self.q = Queue()
self.p = Process(target=Foo, args=(self.q,), daemon=True)
self.p.start()
if __name__ == "__main__":
x = Bar()
sleep(1) But if we make q a local variable if __name__ == "__main__":
Bar()
sleep(1) As such, I believe that this has to do with the class Bar:
def __init__(self) -> None:
q = Queue()
self.p = Process(target=Foo, args=(q,), daemon=True)
self.p.start()
sleep(1)
if __name__ == "__main__":
Bar() Would you agree this seems to be the source of the issue? |
This appears to be a viable workaround at the moment that works wether or not the user instantiates Bar as a variable: from multiprocessing import Process, Queue
from time import sleep
class Foo:
def __init__(self, q) -> None:
pass
class Bar:
def __init__(self) -> None:
self.create_another()
def create_another(self):
if hasattr(self, "q"):
self.p.terminate()
del self.q # Just to prove this works
self.q = Queue()
self.p = Process(target=Foo, args=(self.q,), daemon=True)
self.p.start()
def __del__(self):
self.p.terminate()
del self
if __name__ == '__main__':
# Mini tests
x = Bar()
sleep(1)
x.create_another()
Bar()
Bar().create_another() |
FYI, the example below fails whatever foo is: a function, a new object ( def main():
q = Queue()
p = Process(target=foo, args=(q,))
p.start()
if __name__ == '__main__':
main()
sleep(1) |
If you return q and keep it alive while the process is instantiated it works normally @YvesDup |
Bug report
Bug description:
The following from the docs works:
The following also works:
This works just fine:
But the following does NOT work:
Which now gives this traceback:
The following does work, though:
This should either be documented or fixed, preferably the latter. This behavior is strange and, quite frankly, unexpected. It took me quite a while to figure this out and fix my code but adding an init queue item is not ideal. Note that the following also breaks with the same error:
Moving the
Queue
outside of the class (when calling it) also doesn't fix the issue:But the following works just fine:
This may be related to #116526 but I don't personally think this should be classified as the same issue. May be related to #23376 as well but this may still be a separate issue. Neither address this kind of behavior, however.
CPython versions tested on:
3.12
Operating systems tested on:
macOS
The text was updated successfully, but these errors were encountered: