Python進(jìn)程通信之匿名管道實(shí)例講解
匿名管道
管道是一個單向通道,有點(diǎn)類似共享內(nèi)存緩存.管道有兩端,包括輸入端和輸出端.對于一個進(jìn)程的而言,它只能看到管道一端,即要么是輸入端要么是輸出端.
os.pipe()返回2個文件描述符(r, w),表示可讀的和可寫的.示例代碼如下:
#!/usr/bin/python
import time
import os
def child(wpipe):
print('hello from child', os.getpid())
while True:
msg = 'how are you\n'.encode()
os.write(wpipe, msg)
time.sleep(1)
def parent():
rpipe, wpipe = os.pipe()
pid = os.fork()
if pid == 0:
child(wpipe)
assert False, 'fork child process error!'
else:
os.close(wpipe)
print('hello from parent', os.getpid(), pid)
fobj = os.fdopen(rpipe, 'r')
while True:
recv = os.read(rpipe, 32)
print recv
parent()
輸出如下:
('hello from parent', 5053, 5054)
('hello from child', 5054)
how are you
how are you
how are you
how are you
我們也可以改進(jìn)代碼,不用os.read()從管道中讀取二進(jìn)制字節(jié),而是從文件對象中讀取字符串.這時(shí)需要用到os.fdopen()把底層的文件描述符(管道)包裝成文件對象,然后再用文件對象中的readline()方法讀取.這里請注意文件對象的readline()方法總是讀取有換行符'\n'的一行,而且連換行符也讀取出來.還有一點(diǎn)要改進(jìn)的地方是,把父進(jìn)程和子進(jìn)程的管道中不用的一端關(guān)閉掉.
#!/usr/bin/python
import time
import os
def child(wpipe):
print('hello from child', os.getpid())
while True:
msg = 'how are you\n'.encode()
os.write(wpipe, msg)
time.sleep(1)
def parent():
rpipe, wpipe = os.pipe()
pid = os.fork()
if pid == 0:
os.close(rpipe)
child(wpipe)
assert False, 'fork child process error!'
else:
os.close(wpipe)
print('hello from parent', os.getpid(), pid)
fobj = os.fdopen(rpipe, 'r')
while True:
recv = fobj.readline()[:-1]
print recv
parent()
輸出如下:
('hello from parent', 5108, 5109)
('hello from child', 5109)
how are you
how are you
how are you
如果要與子進(jìn)程進(jìn)行雙向通信,只有一個pipe管道是不夠的,需要2個pipe管道才行.以下示例在父進(jìn)程新建了2個管道,然后再fork子進(jìn)程.os.dup2()實(shí)現(xiàn)輸出和輸入的重定向.spawn功能類似于subprocess.Popen(),既能發(fā)送消息給子進(jìn)程,由能從子子進(jìn)程獲取返回?cái)?shù)據(jù).
#!/usr/bin/python
#coding=utf-8
import os, sys
def spawn(prog, *args):
stdinFd = sys.stdin.fileno()
stdoutFd = sys.stdout.fileno()
parentStdin, childStdout = os.pipe()
childStdin, parentStdout= os.pipe()
pid = os.fork()
if pid:
os.close(childStdin)
os.close(childStdout)
os.dup2(parentStdin, stdinFd)#輸入流綁定到管道,將輸入重定向到管道一端parentStdin
os.dup2(parentStdout, stdoutFd)#輸出流綁定到管道,發(fā)送到子進(jìn)程childStdin
else:
os.close(parentStdin)
os.close(parentStdout)
os.dup2(childStdin, stdinFd)#輸入流綁定到管道
os.dup2(childStdout, stdoutFd)
args = (prog, ) + args
os.execvp(prog, args)
assert False, 'execvp failed!'
if __name__ == '__main__':
mypid = os.getpid()
spawn('python', 'pipetest.py', 'spam')
print 'Hello 1 from parent', mypid #打印到輸出流parentStdout, 經(jīng)管道發(fā)送到子進(jìn)程childStdin
sys.stdout.flush()
reply = raw_input()
sys.stderr.write('Parent got: "%s"\n' % reply)#stderr沒有綁定到管道上
print 'Hello 2 from parent', mypid
sys.stdout.flush()
reply = sys.stdin.readline()#另外一種方式獲得子進(jìn)程返回信息
sys.stderr.write('Parent got: "%s"\n' % reply[:-1])
pipetest.py代碼如下:
#coding=utf-8
import os, time, sys
mypid = os.getpid()
parentpid = os.getppid()
sys.stderr.write('child %d of %d got arg: "%s"\n' %(mypid, parentpid, sys.argv[1]))
for i in range(2):
time.sleep(3)
recv = raw_input()#從管道獲取數(shù)據(jù),來源于父經(jīng)常stdout
time.sleep(3)
send = 'Child %d got: [%s]' % (mypid, recv)
print(send)#stdout綁定到管道上,發(fā)送到父進(jìn)程stdin
sys.stdout.flush()
輸出:
child 7265 of 7264 got arg: "spam"
Parent got: "Child 7265 got: [Hello 1 from parent 7264]"
Parent got: "Child 7265 got: [Hello 2 from parent 7264]"
- Python多進(jìn)程通信Queue、Pipe、Value、Array實(shí)例
- Python進(jìn)程間通信 multiProcessing Queue隊(duì)列實(shí)現(xiàn)詳解
- Python進(jìn)程間通信Queue實(shí)例解析
- Python進(jìn)程間通信Queue消息隊(duì)列用法分析
- python進(jìn)程間通信Queue工作過程詳解
- python實(shí)現(xiàn)進(jìn)程間通信簡單實(shí)例
- python 多進(jìn)程通信模塊的簡單實(shí)現(xiàn)
- Python進(jìn)程間通信之共享內(nèi)存詳解
- python多進(jìn)程實(shí)現(xiàn)進(jìn)程間通信實(shí)例
- python執(zhí)行子進(jìn)程實(shí)現(xiàn)進(jìn)程間通信的方法
- Python進(jìn)程的通信Queue、Pipe實(shí)例分析
相關(guān)文章
解決pyinstaller打包發(fā)布后的exe文件打開控制臺閃退的問題
今天小編就為大家分享一篇解決pyinstaller打包發(fā)布后的exe文件打開控制臺閃退的問題,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-06-06
Python3如何使用tabulate打印數(shù)據(jù)
這篇文章主要介紹了Python3如何使用tabulate打印數(shù)據(jù),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-09-09
python網(wǎng)絡(luò)編程學(xué)習(xí)筆記(二):socket建立網(wǎng)絡(luò)客戶端
看了這一節(jié),突然之間對python網(wǎng)絡(luò)編程學(xué)習(xí)筆記(1)中的一些不理解的問題有了認(rèn)識,至少明白了socket是怎么回事。這里關(guān)于socket的起源等問題就不做筆記記錄了,直接進(jìn)入主題2014-06-06
代碼解析python標(biāo)準(zhǔn)庫logging模塊
這篇文章主要為大家介紹了代碼解析python標(biāo)準(zhǔn)庫logging模塊,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-05-05
Django將默認(rèn)的SQLite更換為MySQL的實(shí)現(xiàn)
今天小編就為大家分享一篇Django將默認(rèn)的SQLite更換為MySQL的實(shí)現(xiàn),具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-11-11
詳解利用Pandas求解兩個DataFrame的差集,交集,并集
這篇文章主要和大家講解一下如何利用Pandas函數(shù)求解兩個DataFrame的差集、交集、并集,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下2022-07-07

