multiprocessing: Implement Pipe-alike.

Unfortunately, any Pipe used for parent/child child communication
needs to be registered with child Process. To get around that, would
need to keep global registry of Pipes, and that's bloat.
pull/118/head
Paul Sokolovsky 2014-05-01 09:41:09 +03:00
rodzic 8e3ce63a8d
commit 7fbc074a13
2 zmienionych plików z 62 dodań i 1 usunięć

Wyświetl plik

@ -1,4 +1,5 @@
import os
import pickle
class Process:
@ -6,15 +7,56 @@ class Process:
def __init__(self, group=None, target=None, name=None, args=(), kwargs={}):
self.target = target
self.args = args
self.kwargs = kwargs
self.pid = 0
self.r = self.w = None
def start(self):
self.pid = os.fork()
if not self.pid:
self.target(*self.args)
if self.r:
self.r.close()
self.target(*self.args, **self.kwargs)
os._exit(0)
else:
if self.w:
self.w.close()
return
def join(self):
os.waitpid(self.pid, 0)
def register_pipe(self, r, w):
"""Extension to CPython API: any pipe used for parent/child
communication should be registered with this function."""
self.r, self.w = r, w
class Connection:
def __init__(self, fd):
self.fd = fd
self.f = open(fd)
def __repr__(self):
return "<Connection %s>" % self.f
def send(self, obj):
s = pickle.dumps(obj)
self.f.write(len(s).to_bytes(4))
self.f.write(s)
def recv(self):
s = self.f.read(4)
l = int.from_bytes(s)
s = self.f.read(l)
return pickle.loads(s)
def close(self):
self.f.close()
def Pipe(duplex=True):
assert duplex == False
r, w = os.pipe()
return Connection(r), Connection(w)

Wyświetl plik

@ -0,0 +1,19 @@
import sys
import os
from multiprocessing import Process, Pipe, Connection
def f(conn):
conn.send([42, None, 'hello'])
conn.send([42, 42, 42])
conn.close()
if __name__ == '__main__':
parent_conn, child_conn = Pipe(False)
print(parent_conn, child_conn)
p = Process(target=f, args=(child_conn,))
# Extension: need to call this for uPy
p.register_pipe(parent_conn, child_conn)
p.start()
print(parent_conn.recv())
print(parent_conn.recv())
p.join()