Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python 3: multiprocessing, EOFError: EOF when reading a line

I wish to have a process continually monitoring RPi input, and set a variable (I have chosen a queue) to True or False to reflect the debounced value. Another process will then capture an image (from a stream). I have written some code just to check I can get multiprocessing and signalling (the queue) working ok (I'm an amature coder...).

It all works fine with threading, but multiprocessing is giving an odd error. Specifically 'multiprocessing, EOFError: EOF when reading a line'. Code outputs:-

this computer has the following number of CPU's 6
OK, started thread on separate processor, now we monitor variable
enter something, True is the key word:
Process Process-1:
Traceback (most recent call last):
  File "c:\Python34\lib\multiprocessing\process.py", line 254, in _bootstrap
    self.run()
  File "c:\Python34\lib\multiprocessing\process.py", line 93, in run
    self._target(*self._args, **self._kwargs)
  File "C:\Users\Peter\Documents\NetBeansProjects\test_area\src\test4.py", line 16, in Wait4InputIsTrue
    ValueIs = input("enter something, True is the key word: ")
EOFError: EOF when reading a line

This module monitors the 'port' (I am using the keyboard as an input):

#test4.py
from time import sleep
from multiprocessing import Lock

def Wait4InputIsTrue(TheVar, TheLock):
    while True:
        sleep(0.2)
        TheLock.acquire()
        #try:
        ValueIs = input("enter something, True is the key word: ")
        #except:
        #    ValueIs = False
        if ValueIs == "True":
            TheVar.put(True)
            print("changed TheVar to True")
        TheLock.release()

This module monitors the status, and acts on it:

#test5.py
if __name__ == "__main__":
    from multiprocessing import Process, Queue, Lock, cpu_count
    from time import sleep
    from test4 import Wait4InputIsTrue

    print("this computer has the following number of CPU's", cpu_count())
    LockIt = Lock()
    IsItTrue = Queue(maxsize = 3)

    Wait4 = Process(target = Wait4InputIsTrue, args = (IsItTrue, LockIt))
    Wait4.start()

    print("OK, started thread on separate processor, now we monitor variable")

    while True:
        if IsItTrue.qsize():
            sleep(0.1)
            print("received input from separate thread:", IsItTrue.get())

Note that I have tried adding a try: to the input statement in test4.py, in which case it keeps printing "enter something, True is the key word: " indefinitely, without a cr.

I added Lock in wild attempt to fix it, makes no difference

Anyone any idea why this is happening?

like image 867
PeterPiper Avatar asked Oct 14 '25 08:10

PeterPiper


1 Answers

Your problem can be boiled down to a simpler script:

import multiprocessing as mp
import sys

def worker():
    print("Got", repr(sys.stdin.read(1)))

if __name__ == "__main__":
    process = mp.Process(target=worker)
    process.start()
    process.join()

When run, it produces

$ python3 i.py
Got ''

Reading zero bytes means the pipe is closed and input(..) turns that into an EOFError exception.

The multiprocessing module doesn't let you read stdin. That makes sense generally because mixing stdin readers from multiple children is a risky business. In fact, digging into the implementation, multiprocessing/process.py explicitly sets stdin to devnull:

                sys.stdin.close()
                sys.stdin = open(os.devnull)

If you are just using stdin for test, then the solution is simple: Don't do that! If you really need user input, life is quite a bit more difficult. You can use additional queues plus code in the parent to prompt users and get input.

like image 155
tdelaney Avatar answered Oct 16 '25 22:10

tdelaney



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!