30

Pythonスクリプトのすべての出力をログに記録したいと思います。私は試した:

import sys

log = []

class writer(object):
    def write(self, data):
        log.append(data)

sys.stdout = writer()
sys.stderr = writer()

さて、「何かを印刷する」とログに記録されます。しかし、たとえば「print'something#」などの構文エラーを作成すると、ログに記録されません。代わりにコンソールに移動します。

Pythonインタープリターからのエラーもキャプチャするにはどうすればよいですか?

私はここで可能な解決策を見ました:

http://www.velocityreviews.com/forums/showpost.php?p=1868822&postcount=3

しかし、2番目の例は/ dev/nullにログインします-これは私が望むものではありません。上記の例やStringIOなどのリストにログインしたいのですが...

また、できればサブプロセスを作成したくありません(そして、そのstdoutとstderrを別々のスレッドで読み取ります)。

4

10 に答える 10

33

次のように stderr をファイルにキャプチャする作業用に作成したソフトウェアがあります。

import sys
sys.stderr = open('C:\\err.txt', 'w')

だから絶対に可能です。

あなたの問題は、ライターの 2 つのインスタンスを作成していることだと思います。

多分もっと似たもの:

import sys

class writer(object):
    log = []

    def write(self, data):
        self.log.append(data)

logger = writer()
sys.stdout = logger
sys.stderr = logger
于 2009-12-24T01:16:19.543 に答える
7

同じコードのコンパイル中にエラーをキャプチャできるPythonコードでは何もできません。どうしてそれができますか?コンパイラがコードのコンパイルを完了できない場合、コンパイラはコードを実行しないため、リダイレクトはまだ有効になっていません。

そこで、(不要な)サブプロセスが登場します。stdoutをリダイレクトするPythonコードを記述してから、Pythonインタープリターを呼び出して他のコードをコンパイルできます。

于 2009-12-24T00:53:25.397 に答える
6

簡単な方法は考えられません。Pythonプロセスの標準エラーは、Pythonファイルオブジェクトよりも低いレベルにあります(C対Python)。

Pythonスクリプトを2番目のPythonスクリプトでラップし、subprocess.Popenを使用できます。単一のスクリプトでこのような魔法を引き出すことも可能です。

import os
import subprocess
import sys

cat = subprocess.Popen("/bin/cat", stdin=subprocess.PIPE, stdout=subprocess.PIPE)
os.close(sys.stderr.fileno())
os.dup2(cat.stdin.fileno(), sys.stderr.fileno())

次に、select.poll()を使用してcat.stdoutを定期的にチェックし、出力を見つけます。

はい、それはうまくいくようです。

私が予測する問題は、ほとんどの場合、Pythonによってstderrに出力されたものが、終了しようとしていることを示していることです。これを処理するためのより一般的な方法は、例外を使用することです。

- - - - -編集

どういうわけか私はos.pipe()関数を逃しました。

import os, sys
r, w = os.pipe()
os.close(sys.stderr.fileno())
os.dup2(w, sys.stderr.fileno())

次に、rから読み取ります

于 2009-12-24T01:09:22.757 に答える
5

このような要求の場合、通常、Python ではなく OS で実行する方がはるかに簡単です。

たとえば、「a.py」を実行し、生成されるすべてのメッセージをファイル「a.out」に記録する場合、次のようになります。

python a.py 2>&1 > a.out

最初の部分は2>&1stderr を stdout (0: stdin、1:stdout、2:stderr) にリダイレクトし、2 番目の部分はそれを a.out というファイルにリダイレクトします。

私の知る限り、このコマンドは Windows、Linux、または MacOS で機能します。他のファイル リダイレクト手法については、os と「ファイル リダイレクト」を検索してください。

于 2017-01-09T21:39:07.523 に答える
3

Python 3.5以降、使用できますcontextlib.redirect_stderr

with open('help.txt', 'w') as f:
    with redirect_stdout(f):
        help(pow)
于 2018-08-27T13:19:25.767 に答える
0
import sys
import tkinter

# ********************************************

def mklistenconsswitch(*printf: callable) -> callable:
    def wrapper(*fcs: callable) -> callable:
        def newf(data):
            [prf(data) for prf in fcs]
        return newf
    stdoutw, stderrw = sys.stdout.write, sys.stderr.write
    funcs = [(wrapper(sys.stdout.write, *printf), wrapper(sys.stderr.write, *printf)), (stdoutw, stderrw)]
    def switch():
        sys.stdout.write, sys.stderr.write = dummy = funcs[0]
        funcs[0] = funcs[1]
        funcs[1] = dummy
    return switch

# ********************************************

def datasupplier():
    i = 5.5
    while i > 0:
        yield i
        i -= .5

def testloop():
    print(supplier.__next__())
    svvitch()
    root.after(500, testloop)

root = tkinter.Tk()
cons = tkinter.Text(root)
cons.pack(fill='both', expand=True)
supplier = datasupplier()
svvitch = mklistenconsswitch(lambda text: cons.insert('end', text))
testloop()
root.mainloop()
于 2016-02-08T00:36:49.963 に答える
0

エラーがある場合、Python はコードを実行しません。ただし、スクリプトを別のスクリプトにインポートして例外をキャッチすることはできます。例:

Script.py

print 'something#

FinalScript.py

from importlib.machinery import SourceFileLoader

try:
    SourceFileLoader("main", "<SCRIPT PATH>").load_module()
except Exception as e:
    # Handle the exception here
于 2018-09-17T18:46:40.873 に答える