Python外壳封装器

4 投票
2 回答
3102 浏览
提问于 2025-04-17 03:39

我正在尝试写一个简单的Python版本的time命令行程序,不过它不是把实际的用户时间和系统时间显示在终端上,而是把这些信息记录到一个数据库里。

我现在的代码是:

wrapper.py

#!/usr/bin/python
import sys
from subprocess import Popen, PIPE
cmd = 'time ' + (' '.join(['"%s"' % v if ' ' in v else v for v in sys.argv[1:]]))
p = Popen(cmd, shell=True, stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=True)
print p.stdout.read()
print p.stderr.read()

为了简单起见,我没有包含数据库插入的代码。

不过,为了说明一个问题,我使用了测试脚本:

#!/usr/bin/python
import time
for i in xrange(3):
    print i
    time.sleep(1)

如果我运行wrapper.py python delay.py,我希望能看到秒数实时打印出来,然后跟着类似这样的内容:

real    0m3.057s
user    0m0.030s
sys 0m0.000s

结果是,我等了3秒没有任何输出,然后才打印出这些内容:

0
1
2

0.02user 0.00system 0:03.03elapsed 0%CPU (0avgtext+0avgdata 21632maxresident)k
0inputs+0outputs (0major+1514minor)pagefaults 0swaps

我该如何实时读取和打印子进程的输出呢?

另外,为什么time的输出和我直接在终端运行时不同,而且在Python脚本中作为子进程运行时输出会变得混乱呢?

2 个回答

0

你需要实时输出结果:

process = subprocess.Popen(shlex.split(command), stdout = subprocess.PIPE, stderr = subprocess.STDOUT)

while True:
  output = process.stdout.read(1)

  if output == '' and process.poll() != None:
    break

  if output != '':
    sys.stdout.write(output)
    sys.stdout.flush()
2

首先,为什么你要用Python来处理输入输出呢?其实可以让子进程的标准输出和错误输出直接和Python的一起处理。其次,不用真的去用时间命令,你可以直接从Python里获取资源使用情况。试试下面这个:

#! /usr/bin/python

import os
import resource
import sys
import time

cmd = ' '.join(sys.argv[1:])
stime = time.time()
os.system(cmd)          # fire off the command
etime = time.time()

# now get the resource utilization
r = resource.getrusage(resource.RUSAGE_CHILDREN)
user_time = r.ru_utime
sys_time = r.ru_stime
# resource doesn't know "clock" time, so we'll just figure that ourselves
real_time = etime - stime

print "real\t" + str(real_time)
print "user\t" + str(user_time)
print "sys\t" + str(sys_time)

这个会以秒为单位打印时间。如果你想让它看起来和时间命令的输出一样,可以按照那个格式来调整。

至于你问题的第二部分,其实有不同的“时间”命令。当你在Python的子进程中运行它时,你得到的是/usr/bin/time的输出。而当你手动运行时,你得到的是shell自带的时间命令。你可以在命令行输入“type -a time”来查看。还有,试着这样运行你的测试程序:“/usr/bin/time ./test.py”,你应该能看到第二种形式的输出。

撰写回答