我设法在我的python脚本中调用并使用终端命令,它正在运行。
但是目前我正在尝试将此命令的“输出”结果保存到文本文件中,但是我收到了错误。
这是我正确执行的初始代码:
import os
os.system("someCmds --proj ARCH --all")
我尝试将输出保存到文本文件时使用的代码:
import os
import sys
sys.stdout=open("output.txt","w")
command = os.system("someCmds --proj ARCH --all")
print command
sys.stdout.close()
但是我收到以下错误 - ValueError: I/O operation on closed file
我在网上发现了这个文件。那我错在哪里?
答案 0 :(得分:2)
这对Python编程部分更适合stackoverflow.com。但是,也有一个面向Unix的组件。
每个进程都有三个众所周知的文件描述符。虽然它们有name-stdin,stdout和stderr,但实际上它们的文件 numbers 分别为0,1和2。要运行程序并捕获其stdout-file-number-1输出,必须将该进程的文件描述符-1连接到文件或管道。
在命令行shell中,有以下语法:
prog > file
在一个进程中运行程序prog
,该进程的stdout连接到已移入descriptor-slot-1的打开的文件描述符。实际上,在系统调用级别上发生的所有事情都很复杂:
fork
系统调用或其中一个变体:这样可以克隆自己。exec
系列调用来终止自己(克隆),但在此过程中,使用程序prog
替换所有内容。这将保留所有打开的文件描述符,包括指向您在步骤3中移动的文件或管道的描述符。一旦exec
成功,您就不再存在且无法执行任何操作。 (如果exec
失败,请报告失败并退出。) Python就是这样,这个多步骤序列全部包含在subprocess
模块中的花哨错误检查中。您可以使用os.system
,而不是使用subprocess.Popen
。它设计用于管道 - 实际上比文件更难 - 所以如果你真的想要重定向到文件,而不是简单地通过一个读取程序的输出管道,您将首先打开文件,然后调用subprocess.Popen
。
在任何情况下,更改Python进程的sys.stdout
都没有用,因为sys.stdout
是一个完全独立于底层文件描述符系统的Python数据结构。通过open
Python流,您可以获得文件描述符(以及Python数据结构),但它不是文件描述符编号-1。无论是什么,基础文件描述符号都必须移动到克隆中 fork
调用之后的<1>位置。即使您使用subprocess.Popen
,Python将移动的唯一描述符(post-fork)也是您作为stdout=
参数传递的描述符。
(子流程&#39; s Popen
接受以下任何一项:
stream.fileno()
来获取描述符编号,或stdin=
,stdout=
还是{{stderr=
的参数。 1}},或subprocess.PIPE
或者,对于stderr=
,subprocess.STDOUT
:这些告诉它Python应该创建一个管道,或者重新使用先前创建的stdout管道来处理特殊{ {1}}案例。该库非常华丽,并且知道如何使用Python回溯报告stderr=subprocess.STDOUT
失败或子进程中发生的各种其他失败。它使用另一个具有close-on-exec的辅助管道来完成此操作。此管道上的EOF表示执行成功;否则到达此额外管道的数据包括失败,使用exec
模块转换为字节流。)