繁体   English   中英

将python脚本中的shell命令输出保存到文本文件

[英]Saving shell command output in python script to text file

我设法在我的 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

当我在网上找到这个文件时,我确实关闭了该文件。 那么我错在哪里?

这其中的 Python 编程部分更适合 stackoverflow.com。 但是,也有一个面向 Unix 的组件。

每个进程都有三个众所周知的文件描述符 虽然它们有名称——stdin、stdout 和 stderr——但它们实际上是通过它们的文件编号来识别的,它们分别是 0、1 和 2。 要运行一个程序并捕获它的标准输出(它的 file-number-1 输出),您必须将该进程的file-descriptor-1 连接到一个文件或管道。

在命令行 shell 中,有这样的语法:

prog > file

运行程序prog ,在其标准输出连接到已移动到描述符插槽 1 的打开文件描述符的进程中。 实际上,在系统调用级别实现所有这些是很复杂的:

  1. 打开文件。 这会产生一个打开的文件描述符,其数量可能高于 2,因为从零到二是您自己的标准输入、标准输出和标准错误。
  2. 使用fork系统调用或其变体之一:这会克隆您自己。
  3. 在克隆中(但不是在原始文件中),文件描述符从现在的任何位置移动到文件描述符 1。然后关闭原始编号较高的描述符(以及您打开但不希望传递的任何其他描述符) )。
  4. 使用exec系列调用之一来终止您自己(克隆),但在此过程中,将所有内容替换为程序prog 这将维护所有打开的文件描述符,包括指向您在步骤 3 中移动的文件或管道的描述符。一旦exec成功,您将不再存在并且无法执行任何操作。 (如果exec失败,报告失败并退出。)
  5. 回到原始()进程,等待 clone-child 执行然后完成,或者失败,或者发生任何事情。

Python 就是这样,这个多步骤序列在subprocess模块中已经为您完成了,并带有花哨的错误检查。 您可以使用os.system而不是使用subprocess.Popen 它被设计为使用管道——实际上比文件更难——所以如果你真的想重定向到一个文件,而不是简单地通过管道读取程序的输出,你需要先打开文件,然后调用subprocess.Popen

在任何情况下,更改 Python 进程的sys.stdout都没有帮助,因为sys.stdout是一个完全独立于底层文件描述符系统的 Python 数据结构。 通过open Python 流,您确实获得了文件描述符(以及 Python 数据结构),但它不是 file-descriptor-number-1。 底层文件描述符编号,无论它是什么,都必须在克隆中的fork调用之后移动到 slot-1 位置。 即使您使用subprocess.Popen ,Python 将移动的唯一描述符(post-fork)是您作为stdout=参数传递的描述符。

(Subprocess 的Popen接受以下任何一种:

  • Python 流:Python 使用stream.fileno()来获取描述符编号,或者
  • 一个整数:Python 假设 this 表示一个打开的文件描述符,应该移动到 fd 0、1 或 2,具体取决于这是stdin=stdout=还是stderr=的参数,或者
  • 特殊值subprocess.PIPE或者,对于stderr=subprocess.STDOUT :这些告诉它 Python 应该创建一个管道,或者为特殊的stderr=subprocess.STDOUT重新使用先前创建的 stdout 管道。

该库非常漂亮,并且知道如何使用 Python exec 、执行失败或子进程中发生的各种其他故障来报告。 它使用另一个带有 close-on-exec 的辅助管道来执行此操作。 此管道上的 EOF 表示执行成功; 否则到达这个额外管道的数据包括失败,使用pickle模块转换为字节流。)

出于某种原因,我无法发布我的问题,所以我想我在这里发表评论。 我需要一些关于在 python 中输出文本的帮助。

我使用 kaldi ASR 训练了一个语言模型,现在我正在尝试将它链接到 vosk API 以制作语音到文本软件。 后端引擎是 kaldi,前端工作涉及 python。 python脚本如下:


from vosk import Model, KaldiRecognizer, SetLogLevel
import os
import wave
import json

fname =  input ( "Enter audio file name: " ) 
wav = ".wav"
txt = ".txt"
transcript = fname + txt
audiofilename = fname + wav

#wav = input( "enter audio filename with extension: " )
wf = wave.open(audiofilename, "rb")
model = Model(".")
rec = KaldiRecognizer(model, wf.getframerate())

results = []
# recognize speech using vosk model

while True:
    data = wf.readframes(4000)

    if len(data) == 0:
        break

    if rec.AcceptWaveform(data):
        part_result = json.loads(rec.Result())
        results.append(part_result)
        print(rec.Result())

    else:
        print(rec.PartialResult())
part_result = json.loads(rec.FinalResult())
results.append(part_result)

# forming a final string from the words
text = ''
for r in results:
    text += r['text'] + ' '

print(f"Vosk thinks you said:\n {text}")         
#print(rec.FinalResult())

# convert list of JSON dictionaries to list of 'Word' objects
list_of_Words = []
for sentence in results:
    if len(sentence) == 1:
        # sometimes there are bugs in recognition 
        # and it returns an empty dictionary
        # {'text': ''}
        continue
    for obj in sentence['result']:
        w = custom_Word.Word(obj)  # create custom Word object
        list_of_Words.append(w)  # and add it to list

wf.close()  # close audiofile

# output to the screen
for word in list_of_words:
    print(word.to_string())``` 

The output is working correctly. Info displayed on Shell is fine.

I cant figure out how to use f.write or similar command to save the shell output (all of it or any particular output I need from the code) and save it to a text file.

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM