[英]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 的打開文件描述符的進程中。 實際上,在系統調用級別實現所有這些是很復雜的:
fork
系統調用或其變體之一:這會克隆您自己。exec
系列調用之一來終止您自己(克隆),但在此過程中,將所有內容替換為程序prog
。 這將維護所有打開的文件描述符,包括指向您在步驟 3 中移動的文件或管道的描述符。一旦exec
成功,您將不再存在並且無法執行任何操作。 (如果exec
失敗,報告失敗並退出。) 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
接受以下任何一種:
stream.fileno()
來獲取描述符編號,或者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.