簡體   English   中英

使用os.pipe和os.fork()問題的Python程序

[英]Python program using os.pipe and os.fork() issue

我最近需要編寫一個執行os.fork()的腳本來分成兩個進程。 子進程成為服務器進程,並使用os.pipe()創建的管道將數據傳遞回父進程。 孩子關閉管道的'r'端,父母像往常一樣關閉管道的'w'端。 我將使用os.fdopen將pipe()的返回值轉換為文件對象。

我遇到的問題是:流程成功分叉,孩子成為服務器。 一切都很好,孩子盡職盡責地將數據寫入管道的開放'w'端。 不幸的是,管道的父端做了兩件奇怪的事情:
A)它阻塞管道'r'端的read()操作。
其次,除非'w'端完全關閉,否則它無法讀取放在管道上的任何數據。

我立即認為緩沖是問題,並添加了pipe.flush()調用,但這些沒有幫助。

任何人都可以解釋為什么數據在寫入結束完全關閉之前不會出現? 是否存在使read()調用無阻塞的策略?

這是我的第一個分叉或使用管道的Python程序,如果我犯了一個簡單的錯誤,請原諒我。

您是在不指定大小的情況下使用read(),還是將管道視為迭代器( for line in f )? 如果是這樣,那可能是你的問題的根源 - read()被定義為在返回之前讀取文件的末尾,而不是只讀取可用於讀取的內容。 這意味着它將阻塞,直到孩子調用close()。

在鏈接到的示例代碼中,這沒關系 - 父進程以阻塞方式運行,並且只是將子進程用於隔離目的。 如果你想繼續,那么要么使用非阻塞IO,就像你發布的代碼一樣(但是要准備處理半完成數據),或者讀取塊(例如r.read(size)或r.readline()) )只會在讀取特定大小/行之前阻止。 (你還需要給孩子打電話)

看起來將管道視為迭代器也使用了一些進一步的緩沖區,因為“ for line in r: ”如果需要立即使用每一行,可能無法滿足您的需求。 有可能禁用它,但只是在fdopen中為緩沖區大小指定0似乎不夠。

下面是一些應該有效的示例代碼:

import os, sys, time

r,w=os.pipe()
r,w=os.fdopen(r,'r',0), os.fdopen(w,'w',0)

pid = os.fork()
if pid:          # Parent
    w.close()
    while 1:
        data=r.readline()
        if not data: break
        print "parent read: " + data.strip()
else:           # Child
    r.close()
    for i in range(10):
        print >>w, "line %s" % i
        w.flush()
        time.sleep(1)

運用

fcntl.fcntl(readPipe, fcntl.F_SETFL, os.O_NONBLOCK)

在調用read()之前解決了這兩個問題。 read()調用不再阻塞,並且數據僅在寫入端的flush()之后出現。

我看到你已經解決了阻止i / o和緩沖的問題。

如果您決定嘗試不同的方法,請注意:subprocess是fork / exec習慣用語的等效/替換。 看起來這不是你正在做的事情:你只有一個fork(而不是exec)並在兩個進程之間交換數據 - 在這種情況下, multiprocessing模塊(在Python 2.6+中)將更適合。

Python應用程序中fork的“父”與“子”部分是愚蠢的。 這是16位unix時代的遺產。 從fork / exec和exec是重要事物的那一天起,這是一種做法,可以充分利用一個小小的處理器。

將Python代碼分成兩個獨立的部分:父級和子級。

父部件應使用子進程來運行子部件。

fork和exec可能發生在那里的某個地方 - 但你不需要關心。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM