This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
标题: print blocks with multiprocessing and buffered output
类型: behavior Stage: resolved
Components: Versions: Python 3.11, Python 3.10, Python 3.9, Python 3.8
process
状态: closed Resolution: duplicate
Dependencies: 后续: Locks in the standard library should be sanitized on fork
View: 6721
分配给: 抄送列表: davin, iritkatriel, moi90, pitrou
优先级: normal 关键字:

Created on 2020-08-13 09:42 by moi90, last changed 2022-04-11 14:59 by admin. This issue is now closed.

文件
文件名 上传时间 Description 编辑
mp_problem.py moi90, 2020-08-13 09:42
Messages (10)
msg375298 - (view) Author: Martin (moi90) * 日期: 2020-08-13 09:42
I experience a problem with multiprocessing and print.

I tried to make a minimal working example, please see the attached file.

WITHOUT the offending print statement in the queue filler thread, everything works:
- pytest experiments/mp_problem.py
- pytest experiments/mp_problem.py -s
- python experiments/mp_problem.py

WITH the offending print statement, not so much:
- pytest experiments/mp_problem.py WORKS (Probably because pytest captures fd 1)
- pytest experiments/mp_problem.py -s FAILS eventually (after a couple of workers have been started)
- python experiments/mp_problem.py FAILS eventually (same).

WITH the offending print statement AND PYTHONUNBUFFERED=1, everything works again:
- pytest experiments/mp_problem.py
- pytest experiments/mp_problem.py -s
- python experiments/mp_problem.py

Environment:
Ubuntu 18.04.5 LTS
python 3.8.5 (hcff3b4d_1) on conda 4.8.3
msg375299 - (view) Author: Martin (moi90) * 日期: 2020-08-13 09:57
python experiments/mp_problem.py also fails for:
- 3.8.3, 3.8.2, 3.8.1, 3.8.0
- 3.7.7
- 3.6.10
msg375300 - (view) Author: Irit Katriel (iritkatriel) * (Python committer) 日期: 2020-08-13 10:30
Try putting a lock on the print statement. See this: https://stackoverflow.com/questions/40356200/python-printing-in-multiple-threads/
msg375350 - (view) Author: Martin (moi90) * 日期: 2020-08-13 21:35
While I appreciate your suggestion, it does not help me much.
The problem that people usually have is that the output is scrambled. That is not the problem I'm dealing with.

I'm experiencing a deadlock caused by the print statement which seems like a python bug to me.

Furthermore, the problem appears in a library that is supposed to be used by other people and I have no control over their use of IO.

The particular behavior seems to be specific to using threading and multiprocessing together:
- If I use multiprocessing.dummy (multiprocessing API implemented with threads; so only a single processes are involved), my example works fine.
- If I use a process instead of a thread to fill the queue (filler = multiprocessing.Process(...); so no threads are involved), my example also works fine.
- Only if I have two threads in the main process and additional processes, the example fails.
msg376581 - (view) Author: Irit Katriel (iritkatriel) * (Python committer) 日期: 2020-09-08 16:43
You're right, this is a different issue. I debugged it a bit and I think the race may be between your print statement and the util._flush_std_streams() in Popen.__init__() of Lib/multiprocessing/popen_fork.py.
msg376583 - (view) Author: Irit Katriel (iritkatriel) * (Python committer) 日期: 2020-09-08 17:01
This may be relevant: https://stackoverflow.com/questions/9337711/subprocess-popen-not-thread-safe


It points to print() being not thread safe and suggests to use sys.stdout.write instead.  That worked for me with your script.
msg396528 - (view) Author: Irit Katriel (iritkatriel) * (Python committer) 日期: 2021-06-25 22:35
Is there anything left here?

I've seen it mentioned on other issues of this sort that mixing multiprocessing and threading leads to problems. Should we document that?
msg396542 - (view) Author: Martin (moi90) * 日期: 2021-06-26 06:59
Yes, I think it should at least be documented.

But then it practically says: "Do not use print in your library because it might be used in a threading context" This sounds unacceptable to me. 

It would be great to "just make it work".

> I debugged it a bit and I think the race may be between your print statement and the util._flush_std_streams()

Why would print deadlock with a flush?
msg396544 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) 日期: 2021-06-26 08:10
This is just issue6721 again.

The workaround is easy: just add `multiprocessing.set_start_method("forkserver")` at the start of your program.

Also, this is more or less documented, though quite tersely:
"""Note that safely forking a multithreaded process is problematic.""
https://docs.python.org/3/library/multiprocessing.html#contexts-and-start-methods
msg396549 - (view) Author: Martin (moi90) * 日期: 2021-06-26 11:08
Thanks for the pointer, @pitrou!
历史
日期 用户 动作 参数
2022-04-11 14:59:34admin修改github: 85711
2021-06-26 11:08:01moi90修改消息: + msg396549
2021-06-26 08:10:31pitrou修改状态: open -> closed
versions: + Python 3.9, Python 3.10, Python 3.11
后续: Locks in the standard library should be sanitized on fork
消息: + msg396544

resolution: duplicate
stage: resolved
2021-06-26 06:59:56moi90修改消息: + msg396542
2021-06-25 22:35:18iritkatriel修改消息: + msg396528
2020-09-08 17:01:23iritkatriel修改消息: + msg376583
2020-09-08 16:43:01iritkatriel修改消息: + msg376581
2020-08-14 08:51:51ned.deily修改抄送: + pitrou, davin
2020-08-13 21:35:36moi90修改消息: + msg375350
2020-08-13 10:30:41iritkatriel修改抄送: + iritkatriel
消息: + msg375300
2020-08-13 09:57:27moi90修改消息: + msg375299
2020-08-13 09:42:10moi90创建