在函数运行时写入easygui文本框? [英] Writing to easygui textbox as function is running?

查看:121
本文介绍了在函数运行时写入easygui文本框?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我当前正在使用easygui运行脚本以接收用户输入.在命令行中运行的旧脚本仅会打印用户在命令行中需要知道的所有内容,但是我将其更改为在需要输入时在新的easygui框中输出通知.

I am currently running a script using easygui to receive the user input. The old script that ran in a command line would just print anything the user needed to know in the command line, but I've changed it to output notifications in new easygui boxes when there are required inputs.

我想做的就是取得进展,正在运行的功能中的每个动作,在完成时打印到文本框中.在命令行中,我只能使用print "text",但是我无法在easygui中使其实时发生.目前,我正在添加一个列表,因此我有一个文本框,该文本框会在所有操作完成后显示函数的结果,但是我希望大型的文本框窗口能够弹出并在注释过程完成时将行打印出来.这可行吗?

Want I want to do is have the progress, each action inside the functions that are running, print into a text box as they complete. In command line I could just use print "text" but I can't get it to happen realtime in easygui. Currently I'm appending a list so I have a textbox that displays the results of the function once everything is complete, but I'd like for the large textbox window to pop up and print the line out whenever a process of note completes. Is this doable?

这是我添加列表的方式:

Here is how I'm appending the list:

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)

推荐答案

我认为没有简单的方法可以使EasyGUI的textbox函数执行您想要的功能,而无需修改模块.由于它是一个函数而不是一个类,因此您甚至无法从中派生一个子类,以便轻松地重用其代码.

I don't think there's any simple way of getting EasyGUI's textbox function to do what you want short of modifying the module. Since it's a function not a class, you can't even derive a subclass from it in order to easily reuse its code.

但是,创建一个单独的Tkinter窗口是完全可行的,该窗口使用我在

However it's completely feasible to create a separate Tkinter window that just displays lines of text as they are sent to it using an enhanced version of some code I found once in a thread on the comp.lang.python newsgroup.

原始代码旨在捕获并显示通常不具有stderr输出句柄的GUI应用程序中的stderr输出,因此该模块被命名为errorwindow.但是,我对其进行了修改,以便能够将stderrstdout都重定向到我开发的一个基于easygui的应用程序中的此类窗口,但是我从没想过要重命名它或更新其中的注释以提及stdout重定向. ;¬)

The original code was designed to catch and display only stderr output from a GUI application which normally doesn't have stderr output handle, so the module was named errorwindow. However I modified it to be able redirect both stderr and stdout to such windows in one easygui-based app I developed, but I never got around to renaming it or updating the comments in it to also mention stdout redirection. ;¬)

无论如何,该模块通过定义和创建名为OutputPipe的类文件类的两个实例来工作,并将它们分配给sys.stdoutsys.stderr I/O流文件对象,它们分别是通常在Python .pyw GUI应用程序中(在Windows上)None.当输出首先发送到其中一个时,同一个模块作为单独的Python进程启动,其stdinstdoutstderr I/O句柄通过原始进程进行管道传输.

Anyway, the module works by defining and creating two instances of a file-like class named OutputPipe when it's imported and assigns them to the sys.stdout and sys.stderr I/O stream file objects which are usually None in a Python .pyw GUI applications (on Windows). When output is first sent to either one of these, the same module is launched as separate Python process with its stdin, stdout, and stderr I/O handles piped with the original process.

发生了很多事情,但是如果没有其他事情,只需对其进行一些研究,可能会为您提供一些有关如何使easyguitextbox进行所需操作的想法.希望这会有所帮助.

There's a lot going on, but if nothing else, with a little study of it might give you some ideas about how to get easygui's textbox to do what you want. Hope this helps.

注意:发布的代码适用于Python 2.x,在

Note: The code posted is for Python 2.x, there's a modified version that will work in both Python 2 and 3 in my answer to another question, if anyone is interested.

文件 errorwindow.py:

File errorwindow.py:

# references:
#   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')

这篇关于在函数运行时写入easygui文本框?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆