簡體   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