os.system(sort)疑惑

os.system(sort)疑惑

python程序需要调用如下的sort命令:

sort -t@ -rink1 /data1/admatch//datamanager/logAna//his//maxRate/stats/20080523/1_max_rate.dat.tmp -T /data2/search/.SortTmp/|head -n100 > /data1/admatch//datamanager/logAna//his//maxRate/stats/20080523/1_max_rate.dat

python执行的时候经常会输出如下的错误:
sort: write failed: -: Broken pipe

其中,1_max_rate.dat.tmp  117KB
不知道为什么会出现这个错误;如果我在shell手动调用这个sort命令,则不会出现错误。
先谢谢各位了!
up一下!呵呵
看到你在shell版发的帖子,发出了这样的感慨:
但我个人觉得:如果在shell脚本里遇到,数据量大,计算量也大的应用的时候,最好不要使用管道。存成临时文件会更安全
和强壮些。(个人想法,欢迎批评指正!)
其实这并不是管道的问题,使用管道反而会提高效率,就拿你的例子来说sort file |head -n 100,如果file这个文件很大,而head只需要前100行就够了,何必要把整个文件的内容都写入管道呢,这不是多此一举嘛。
对于管道来说写一个读断已经关闭的管道,会产生SIGPIPE信号,在这里head读完100行之后就结束了,sort再往管道里面写就会接收到SIGPIPE信号,而sort是不会显示的处理信号的。在一个程序刚启动时,会把在父进程中设置为捕捉的信号,设置为默认动作,设置为忽略的不做改变。在登录shell中对于SIGPIPE的动作是默认动作,也就是进程结束。所以在终端下执行sort这个命令接收到SIGPIPE信号时,进程就直接退出了,所以不会产生出错信息。当然也不是正常结束的,只不过你看不到出错信息罢了。而python启动后,则会把SIGPIPE设置为忽略。在sort进程中接收到此信号时,也会忽略这个信号,继续执行。然后sort发现write的返回值为-1,就认为产生了错误,所以会打印出错信息。
你可以做一个实验,在python中import singal,然后signal.singal(signal.SIGPIPE,signal.SIG_DFL),把SIGPIPE设置为默认动作,然后再执行sort命令,你就不会看到出错信息了。


QUOTE:
原帖由 ocean390 于 2008-5-27 15:05 发表
看到你在shell版发的帖子,发出了这样的感慨:
但我个人觉得:如果在shell脚本里遇到,数据量大,计算量也大的应用的时候,最好不要使用管道。存成临时文件会更安全
和强壮些。(个人想法,欢迎批评指正!)
...

收藏。

不妨用os.popen().readline 读100行出来。
ocean390的分析十分到位!
兄弟我学到很多东西!多谢!我当时咋就没想出来呢!
难怪我当时在分析生成的文件的时候,发现结果是正确的。
另外从分析中我也觉得,利用broken pipe,也正是使用管道以提高效率的原因之一。

如此精辟之分岂能独享!再up一下!

save as...


QUOTE:
原帖由 fufeiwxy 于 2008-5-28 17:50 发表
ocean390的分析十分到位!
兄弟我学到很多东西!多谢!我当时咋就没想出来呢!
难怪我当时在分析生成的文件的时候,发现结果是正确的。
另外从分析中我也觉得,利用broken pipe ...



[Copy to clipboard] [ - ]
CODE:
import os
import sys
import time
import traceback

fifoname = '/tmp/pipefifo' # must open same name

def child():
        pipeout= os.open(fifoname, os.O_WRONLY) # open fifo pipe file as fd
        zzz = 0
        while True:
                try:
                        time.sleep(zzz)
                        os.write(pipeout, 'Spam %03d\n' % zzz)
                except OSError:
                        exc_info = sys.exc_info()
#                        print exc_info[0]
                        print exc_info[1]
#                        traceback.print_tb(exc_info[2])
                        if str(exc_info[1])[-11:].lower() == 'broken pipe':
                                print 'Consumer had exited...'
                                lets_exit()
                except KeyboardInterrupt:
                        os.write(pipeout,'Byebye\n')
                        print 'Byebye message had sent...'
                        lets_exit()
                else:
                        zzz = (zzz+1) %5

def lets_exit():
        print 'OK, byebye'
        sys.exit()


def parent():
        pipein = open(fifoname, 'r') # open fifo as stdio object
        while True:
                try:
                        line = pipein.readline()[:-1] # block until data sent
                        if line:
                                print 'Parent %d got "%s" at %s' % (os.getpid(), line, time.time())
                                if line[:3].lower() == 'bye':
                                        print 'Proceduer had exited...'
                                        lets_exit()
                except  KeyboardInterrupt:
                                lets_exit()

if __name__ == '__main__':
        if not os.path.exists(fifoname):
                os.mkfifo(fifoname) # create a named pipe file
        if len(sys.argv) == 1: # run as parent if no args
                parent()
        else: # else run as child process
                child()

不太清楚要说明什么?