Python多进程环境下终端输入时暂停其他进程的实现及EOFError问题解决
EOFError When Using input() in Multiple Python Processes The root cause of your EOFError is straightforward: when you run multiple subprocesses, they all share the same standard input (stdin) stream from the terminal. However, terminal input can only be read by one process at a time. When one process is waiting for input, another process that tries to call input() will find the input stream empty (since the terminal can't send input to two processes simultaneously), resulting in the EOF error.
Here are two reliable solutions to handle this scenario:
Solution 1: Centralize Input Handling in the Main Process (Recommended)
The best approach is to let the main process handle all terminal input, and use inter-process communication (IPC) like multiprocessing.Queue to send input requests from subprocesses to the main process, then return the user's input back to the requesting subprocess. This completely avoids subprocesses competing for the stdin stream.
Modified Code Files:
Code_One.py
from time import sleep def main(input_queue): sleep(1) print('run') sleep(1) print('run') sleep(1) # Send input request to main process input_queue.put(('code_one', 'Please, give the number:')) # Wait for the input result user_input = input_queue.get() print(f"Code_One received input: {user_input}")
Code_Two.py
from time import sleep def main(input_queue): sleep(2) # Send input request to main process input_queue.put(('code_two', 'Please, give the number:')) # Wait for the input result user_input = input_queue.get() print(f"Code_Two received input: {user_input}") sleep(1) print('run 2') sleep(1) print('run 2') sleep(1) print('run 2') sleep(1) print('run 2') sleep(1) print('run 2')
Main_Code.py
import Code_One import Code_Two import multiprocessing from time import sleep def input_handler(input_queue): while True: # Wait for input requests from subprocesses process_name, prompt = input_queue.get() # Exit signal from main process if process_name == 'exit': break # Main process handles the input user_input = input(prompt) # Send input back to the requesting subprocess input_queue.put(user_input) def main(): while True: input_queue = multiprocessing.Queue() # Start input handler process (could also use a thread, since it's IO-bound) handler_process = multiprocessing.Process(target=input_handler, args=(input_queue,)) handler_process.start() # Start business subprocesses with the queue pression = multiprocessing.Process(target=Code_One.main, args=(input_queue,)) xgoals = multiprocessing.Process(target=Code_Two.main, args=(input_queue,)) pression.start() xgoals.start() # Wait for business processes to finish pression.join() xgoals.join() # Send exit signal to input handler input_queue.put(('exit', '')) handler_process.join() print('Done') sleep(5) if __name__ == '__main__': main()
How This Works:
- Subprocesses never directly call
input(); instead, they send a request (with a prompt) to the main process via the queue. - The dedicated
input_handlerprocess (or thread) listens for these requests, uses the main process's stdin to get user input, and sends the result back through the queue. - This ensures only one process (the handler) ever interacts with the terminal input stream, eliminating the EOF error entirely.
Solution 2: Use a Cross-Process Lock to Synchronize Input Access
If you prefer a simpler approach and don't need to separate input logic from business logic, you can use a multiprocessing.Lock to ensure only one subprocess can call input() at a time.
Modified Code Files:
Code_One.py
from time import sleep def main(input_lock): sleep(1) print('run') sleep(1) print('run') sleep(1) # Acquire lock before reading input with input_lock: user_input = input('Please, give the number:') print(f"Code_One received input: {user_input}")
Code_Two.py
from time import sleep def main(input_lock): sleep(2) # Acquire lock before reading input with input_lock: user_input = input('Please, give the number:') print(f"Code_Two received input: {user_input}") sleep(1) print('run 2') sleep(1) print('run 2') sleep(1) print('run 2') sleep(1) print('run 2') sleep(1) print('run 2')
Main_Code.py
import Code_One import Code_Two import multiprocessing from time import sleep def main(): while True: # Create a lock shared across processes input_lock = multiprocessing.Lock() pression = multiprocessing.Process(target=Code_One.main, args=(input_lock,)) xgoals = multiprocessing.Process(target=Code_Two.main, args=(input_lock,)) pression.start() xgoals.start() pression.join() xgoals.join() print('Done') sleep(5) if __name__ == '__main__': main()
Limitations:
- While the lock prevents concurrent calls to
input(), it doesn't fix the underlying issue of shared stdin. In edge cases, you might still run into unexpected behavior (e.g., if a subprocess's prompt is overwritten by another's output). - This approach is less flexible than the centralized input handler if you need to add more complex input logic later.
内容的提问来源于stack exchange,提问作者Digital Farmer

