fork 是 python linux下 os 模块下的一个方法,用来创建一个子进程。今天遇到这个问题,所以找文章来稍微了解一下。以下来自http://www.myelin.co.nz/post/2003/3/13/#200303135。不当之处多指教。
1、有时,程序在一个进程中运行可能会遇到一些问题。如进程可能会占用过多的内存或者打开太多的文件,或者根本无法运行。
2、一般来说,需要将进程分为两个,在子进程中执行一些代码,然后向父进程总返回结果。
这个过程是通过管道来实现的。os.pipe()创建一个管道。一个管道包括两个端,一个读(父进程)一个写(子进程)。子进程将结果写入写端,然后关闭之。父进程从读端读出。
以os.fork()创建新进程,复制所有文件描述符。则父子进程都有了管道的读端和写端的拷贝。直到管道一端的所有拷贝都被关闭,那么管道才关闭,因而在创建子进程之后需要调用os.close()关闭父进程的写端。
所以,运行过程是:
---创建管道
---创建子进程。
子进程:
----需要关闭管道读端
----开始执行
----向写端写入结果
----进程死亡
父进程:
----关闭管道写端
----从读端读取数据直到子进程死亡或者关闭
----调用waitpid方法确保子进程已经被撤销(在FreeBSD中不这么做,那么子进程永远不会被死亡)
----进程输出
3、代码
#!/usr/bin/env python
import os, sys
print "I'm going to fork now - the child will write something to a pipe, and the parent will read it back"
r, w = os.pipe() # r,w是文件描述符, 不是文件对象
pid = os.fork()
if pid:
# 父进程
os.close(w) # 关闭一个文件描述符
r = os.fdopen(r) # 将r转化为文件对象
print "parent: reading"
txt = r.read()
os.waitpid(pid, 0) # 确保子进程被撤销
else:
# 子进程
os.close(r)
w = os.fdopen(w, 'w')
print "child: writing"
w.write("here's some text from the child")
w.close()
print "child: closing"
sys.exit(0)
print "parent: got it; text =", txt
note here
Re: Subprocess confusion: how file-like must stdin be?
Cameron Laird
Fri, 18 Aug 2006 05:10:51 -0700
In article ,
Nick Craig-Wood wrote:
>Dennis Lee Bieber wrote:
>> On Thu, 17 Aug 2006 17:16:25 +0000, [EMAIL PROTECTED] (Cameron Laird)
>> declaimed the following in comp.lang.python:
>>
>> > Question:
>> > import subprocess, StringIO
>> >
>> > input = StringIO.StringIO("abcdefgh\nabc\n")
>>
>> Here you override the builtin function "input()"
>> > # I don't know of a compact, evocative, and
>> > # cross-platform way to exhibit this behavior.
>> > # For now, depend on cat(1).
>> > p = subprocess.Popen(["cat"], stdout = subprocess.PIPE,
>> > stdin = response)
>>
>> Here you specify the non-existant "response"
>
>Assume the OP meant to write this
>
>>>> import subprocess, StringIO
>>>> inp = StringIO.StringIO("abcdefgh\nabc\n")
>>>> p = subprocess.Popen(["cat"], stdout = subprocess.PIPE, stdin = inp)
>Traceback (most recent call last):
> File "", line 1, in ?
> File "/usr/lib/python2.4/subprocess.py", line 534, in __init__
> (p2cread, p2cwrite,
> File "/usr/lib/python2.4/subprocess.py", line 830, in _get_handles
> p2cread = stdin.fileno()
>AttributeError: StringIO instance has no attribute 'fileno'
>>>>
.
.
.
Yes; my apologies for the confusion I introduced by "editing
for publication", and doing it badly.
Your interactive session does indeed exhibit the behavior that
puzzles me. My expectation was that StringIO and the std*
parameters to Popen() were made for each other; certainly there
are many cases where stdout and stderr can be redirected *to* a
StringIO. Is it simply the case that stdin demands a more
file-like object? While that disappoints me, I certainly can
program around it. My question, then: does stdin effectively
require something really in the filesystem, or perhaps the
stdout of a previous subprocess? Is there no built-in way to
feed it an in-memory construct?
--
http://mail.python.org/mailman/listinfo/python-list
Re: Subprocess confusion: how file-like must stdin be?
Laurent Pointal
Fri, 18 Aug 2006 06:55:59 -0700
Cameron Laird a écrit :
> In article ,
> Nick Craig-Wood wrote:
>> Dennis Lee Bieber wrote:
>>> On Thu, 17 Aug 2006 17:16:25 +0000, [EMAIL PROTECTED] (Cameron Laird)
>>> declaimed the following in comp.lang.python:
>>>
>>>> Question:
>>>> import subprocess, StringIO
>>>>
>>>> input = StringIO.StringIO("abcdefgh\nabc\n")
>>> Here you override the builtin function "input()"
>>>> # I don't know of a compact, evocative, and
>>>> # cross-platform way to exhibit this behavior.
>>>> # For now, depend on cat(1).
>>>> p = subprocess.Popen(["cat"], stdout = subprocess.PIPE,
>>>> stdin = response)
>>> Here you specify the non-existant "response"
>> Assume the OP meant to write this
>>
>>>>> import subprocess, StringIO
>>>>> inp = StringIO.StringIO("abcdefgh\nabc\n")
>>>>> p = subprocess.Popen(["cat"], stdout = subprocess.PIPE, stdin = inp)
>> Traceback (most recent call last):
>> File "", line 1, in ?
>> File "/usr/lib/python2.4/subprocess.py", line 534, in __init__
>> (p2cread, p2cwrite,
>> File "/usr/lib/python2.4/subprocess.py", line 830, in _get_handles
>> p2cread = stdin.fileno()
>> AttributeError: StringIO instance has no attribute 'fileno'
> .
> .
> .
> Yes; my apologies for the confusion I introduced by "editing
> for publication", and doing it badly.
>
> Your interactive session does indeed exhibit the behavior that
> puzzles me. My expectation was that StringIO and the std*
> parameters to Popen() were made for each other; certainly there
> are many cases where stdout and stderr can be redirected *to* a
> StringIO. Is it simply the case that stdin demands a more
> file-like object? While that disappoints me, I certainly can
> program around it. My question, then: does stdin effectively
> require something really in the filesystem, or perhaps the
> stdout of a previous subprocess? Is there no built-in way to
> feed it an in-memory construct?
As this is a pipe at OS level, there may be no other way than using
os-level tools (ie. real files with fileno), maybe creating an anonymous
pipe, writing to it (relying on pipe buffering by the OS to avoid the
creation of a writer thread), and giving this pipe (which should have a
fileno) to the subprocess.Popen stdin parameter.
Such a construction (pipe/writer thread) would be welcome as standard
subprocess tool.
A+
Laurent.
--
http://mail.python.org/mailman/listinfo/python-listReply via email to