1

現在、ユーザー入力を受け取るために easygui を使用してスクリプトを実行しています。コマンド ラインで実行された古いスクリプトは、ユーザーがコマンド ラインで知る必要があるものを出力するだけでしたが、必要な入力がある場合に新しい easygui ボックスに通知を出力するように変更しました。

私がやりたいのは、進行状況、実行中の関数内の各アクション、完了時にテキスト ボックスに出力することです。コマンドラインでは使用できprint "text"ましたが、easyguiではリアルタイムで実行できません。現在、リストを追加しているので、すべてが完了すると関数の結果を表示するテキストボックスがありますが、大きなテキストボックスウィンドウがポップアップして、メモのプロセスが完了するたびに行を印刷したいと思います. これは実行可能ですか?

リストを追加する方法は次のとおりです。

result_list = []
record_str = "\n Polling has completed for 502."
result_list.append(record_str)
eg.textbox("Polling Status", "Daily polling completion status:", result_list)
4

1 に答える 1

4

textboxモジュールを変更する以外に、EasyGUI の機能を使用して目的を達成する簡単な方法はないと思います。これはクラスではなく関数であるため、コードを簡単に再利用するためにサブクラスを派生させることさえできません。

ただし、ニュースグループTkinterのスレッドで一度見つけたコードの拡張バージョンを使用して、送信されたテキスト行を表示するだけの別のウィンドウを作成することは完全に実行可能です。comp.lang.python

元のコードはstderr、通常は出力ハンドルを持たない GUI アプリケーションからの出力のみをキャッチして表示するように設計されていstderrたため、モジュールの名前はerrorwindow. ただし、開発した1つのベースのアプリで とそのようなウィンドウの両方stderrにリダイレクトできるように変更しましたが、名前を変更したり、その中のコメントを更新してリダイレクトについて言及したりすることはできませんでした。stdouteasyguistdout;¬)

とにかく、モジュールは、edOutputPipeのときに名前が付けられたファイルのようなクラスの 2 つのインスタンスを定義して作成し、通常Python GUI アプリケーション (Windows 上)にある I/O ストリーム ファイル オブジェクトにそれらを割り当てます。出力が最初にこれらのいずれかに送信されると、同じモジュールが別の Python プロセスとして起動され、その、、およびI/O ハンドルが元のプロセスにパイプされます。importsys.stdoutsys.stderrNone.pywstdinstdoutstderr

たくさんのことが起こっていますが、少なくともそれを少し研究することで、あなたが望むことをする方法についていくつかのアイデアが得られるかもしれませeasyguitextbox. お役に立てれば。

注:投稿されたコードは Python 2.x 用です。誰かが興味を持っている場合は、別の質問への回答で Python 2 と 3 の両方で動作する修正バージョンがあります。

ファイルerrorwindow.py:

# Code derived from Bryan Olson's source posted in this related Usenet discussion:
#   https://groups.google.com/d/msg/comp.lang.python/HWPhLhXKUos/TpFeWxEE9nsJ
#   https://groups.google.com/d/msg/comp.lang.python/HWPhLhXKUos/eEHYAl4dH9YJ
#
#   Here's a module to show stderr output from console-less Python
#   apps, and stay out of the way otherwise. I plan to make a ASPN
#   recipe of it, but I thought I'd run it by this group first.
#
#   To use it, import the module. That's it. Upon import it will
#   assign sys.stderr.
#
#   In the normal case, your code is perfect so nothing ever gets
#   written to stderr, and the module won't do much of anything.
#   Upon the first write to stderr, if any, the module will launch a
#   new process, and that process will show the stderr output in a
#   window. The window will live until dismissed; I hate, hate, hate
#   those vanishing-consoles-with-critical-information.
#
#   The code shows some arguably-cool tricks. To fit everthing in
#   one file, the module runs the Python interpreter on itself; it
#   uses the "if __name__ == '__main__'" idiom to behave radically
#   differently upon import versus direct execution. It uses TkInter
#   for the window, but that's in a new process; it does not import
#   TkInter into your application.
#
#   To try it out, save it to a file -- I call it "errorwindow.py" -
#   - and import it into some subsequently-incorrect code. For
#   example:
#
#        import errorwindow
#
#        a = 3 + 1 + nonesuchdefined
#
#   should cause a window to appear, showing the traceback of a
#   Python NameError.
#
#   --
#   --Bryan
#   ----------------------------------------------------------------
#
#   martineau - Modified to use subprocess.Popen instead of the os.popen
#               which has been deprecated since Py 2.6. Changed so it
#               redirects both stdout and stderr. Added numerous
#               comments, and also inserted double quotes around paths
#               in case they have embedded space characters in them, as
#               they did on my Windows system.

"""
    Import this module into graphical Python apps to provide a
    sys.stderr. No functions to call, just import it. It uses
    only facilities in the Python standard distribution.

    If nothing is ever written to stderr, then the module just
    sits there and stays out of your face. Upon write to stderr,
    it launches a new process, piping it error stream. The new
    process throws up a window showing the error messages.
"""
import subprocess
import sys
import thread
import os

if __name__ == '__main__':  # when spawned as separate process
    # create window in which to display output
    # then copy stdin to the window until EOF
    # will happen when output is sent to each OutputPipe created
    from Tkinter import BOTH, END, Frame, Text, TOP, YES
    import tkFont
    import Queue

    queue = Queue.Queue(100)

    def read_stdin(app, bufsize=4096):
        fd = sys.stdin.fileno()  # gets file descriptor
        read = os.read
        put = queue.put
        while True:
            put(read(fd, bufsize))

    class Application(Frame):
        def __init__(self, master=None, font_size=8, text_color='#0000AA', rows=25, cols=100):
            Frame.__init__(self, master)
            # argv[0]: name of this script (not used)
            # argv[1]: name of script that imported this module
            # argv[2]: name of redirected stream (optional)
            if len(sys.argv) < 3:
                title = "Output Stream from %s" % (sys.argv[1],)
            else:
                title = "Output Stream '%s' from %s" % (sys.argv[2], sys.argv[1])
            self.master.title(title)
            self.pack(fill=BOTH, expand=YES)
            font = tkFont.Font(family='Courier', size=font_size)
            width = font.measure(' '*(cols+1))
            height = font.metrics('linespace')*(rows+1)
            self.configure(width=width, height=height)
            self.pack_propagate(0)  # force frame to be configured size
            self.logwidget = Text(self, font=font)
            self.logwidget.pack(side=TOP, fill=BOTH, expand=YES)
            # Disallow key entry, but allow copy with <Control-c>
            self.logwidget.bind('<Key>', lambda x: 'break')
            self.logwidget.bind('<Control-c>', lambda x: None)
            self.logwidget.configure(foreground=text_color)
            #self.logwidget.insert(END, '==== Start of Output Stream ====\n\n')
            #self.logwidget.see(END)
            self.after(200, self.start_thread, ())

        def start_thread(self, _):
            thread.start_new_thread(read_stdin, (self,))
            self.after(200, self.check_q, ())

        def check_q(self, _):
            log = self.logwidget
            log_insert = log.insert
            log_see = log.see
            queue_get_nowait = queue.get_nowait
            go = True
            while go:
                try:
                    data = queue_get_nowait()
                    if not data:
                        data = '[EOF]'
                        go = False
                    log_insert(END, data)
                    log_see(END)
                except Queue.Empty:
                    self.after(200, self.check_q, ())
                    go = False

    app = Application()
    app.mainloop()

else: # when module is first imported
    import traceback
    class OutputPipe(object):
        def __init__(self, name=''):
            self.lock = thread.allocate_lock()
            self.name = name

        def __getattr__(self, attr):
            if attr == 'pipe':  # pipe attribute hasn't been created yet
                # launch this module as a separate process to display any output
                # it receives.
                # Note: It's important to put double quotes around everything in case
                # they have embedded space characters.
                command = '"%s" "%s" "%s" "%s"' % (sys.executable,                # command
                                                   __file__,                      # argv[0]
                                                   os.path.basename(sys.argv[0]), # argv[1]
                                                   self.name)                     # argv[2]

                # sample command and arg values on receiving end:
                #   E:\Program Files\Python\python[w].exe                         # command
                #   H:\PythonLib\TestScripts\PyRemindWrk\errorwindow.py           # argv[0]
                #   errorwindow.py                                                # argv[1]
                #   stderr                                                        # argv[2]

                # execute this script as __main__ with a stdin PIPE for sending output to it
                try:
                    # had to make stdout and stderr PIPEs too, to make it work with pythonw.exe
                    self.pipe = subprocess.Popen(command, bufsize=0,
                                                 stdin=subprocess.PIPE,
                                                 stdout=subprocess.PIPE,
                                                 stderr=subprocess.PIPE).stdin
                except Exception:
                    # output exception info to a file since this module isn't working
                    exc_type, exc_value, exc_traceback = sys.exc_info()
                    msg = ('%r exception in %s\n' %
                            (exc_type.__name__, os.path.basename(__file__)))
                    with open('exc_info.txt', 'wt') as info:
                        info.write('msg:' + msg)
                        traceback.print_exc(file=info)
                    sys.exit('fatal error occurred spawning output process')

            return super(OutputPipe, self).__getattribute__(attr)

        def write(self, data):
            with self.lock:
                self.pipe.write(data)  # 1st reference to pipe attr will cause it to be created

    # redirect standard output streams in the process importing the module
    sys.stderr = OutputPipe('stderr')
    sys.stdout = OutputPipe('stdout')
于 2013-08-06T22:06:02.920 に答える