GVKun编程网logo

在Tkinter小部件中显示子流程的实时输出(利用tkinter模块中的子模块)

8

在本文中,我们将详细介绍在Tkinter小部件中显示子流程的实时输出的各个方面,并为您提供关于利用tkinter模块中的子模块的相关解答,同时,我们也将为您带来关于python–在Tkinter中滚动

在本文中,我们将详细介绍在Tkinter小部件中显示子流程的实时输出的各个方面,并为您提供关于利用tkinter模块中的子模块的相关解答,同时,我们也将为您带来关于python – 在Tkinter中滚动一组小部件、Python-子流程命令的实时输出、Python:Tkinter小部件背景(按钮,条目等)、Raspberry Pi-如何通过HDMI显示某些TKinter小部件-在VNC上运行另一个小部件时的有用知识。

本文目录一览:

在Tkinter小部件中显示子流程的实时输出(利用tkinter模块中的子模块)

在Tkinter小部件中显示子流程的实时输出(利用tkinter模块中的子模块)

我有以下代码(python2.7):

def btnGoClick(p1):    params = w.line.get()    if len(params) == 0:        return    # create child window    win = tk.Toplevel()    win.title(''Bash'')    win.resizable(0, 0)    # create a frame to be able to attach the scrollbar    frame = ttk.Frame(win)    # the Text widget - the size of the widget define the size of the window    t = tk.Text(frame, width=80, bg="black", fg="green")    t.pack(side="left", fill="both")    s = ttk.Scrollbar(frame)    s.pack(side="right", fill="y")    # link the text and scrollbar widgets    s.config(command=t.yview)    t.config(yscrollcommand=s.set)    frame.pack()    process = subprocess.Popen(["<bashscript>", params], shell=False,        stdout=subprocess.PIPE, stderr=subprocess.STDOUT)    while True:        out = process.stdout.readline()        if out == '''' and process.poll() is not None:            break        print out        t.insert(tk.END, out)

“ longrunning” bash脚本的输出是实时捕获的(显示在控制台中),但是Tkinter窗口仅在子进程结束后显示!

如何在子进程启动之前实时显示窗口并更新其内容?

答案1

小编典典

终于我找到了解决方案。窗口构建后,必须添加:

frame.pack()# force drawing of the windowwin.update_idletasks()

然后,在小部件中插入每行之后,还必须仅在小部件上使用相同的方法强制刷新。

# insert the line in the Text widgett.insert(tk.END, out)# force widget to display the end of the text (follow the input)t.see(tk.END)# force refresh of the widget to be sure that thing are displayedt.update_idletasks()

python – 在Tkinter中滚动一组小部件

python – 在Tkinter中滚动一组小部件

我想在Tkinter GUI中创建可以滚动的各个小部件的整列,如下所示:

Tkinter can only attach scrollbars to certain widgets,其中不包括框架.制作可分割列是接口中的常见做法,应该有一个简单的解决方案,但到目前为止,我所能找到的只是this hacky example of a scrollable frame,using a canvas widget.在similar stack overflow question中使用了类似的hacky解决方案.

在Tkinter中是否有一种普遍接受的方法可以创建一个可滚动的列或一组小部件?

解决方法

使用画布的解决方案是解决此问题的常用方法.它真的不是那么hacky,最终结果可以与原生滚动容器小部件无法区分.

如果您要创建单个列,则另一个选项是使用文本窗口小部件,并使用窗口小部件嵌入其他窗口小部件的功能.插入小部件,然后插入换行符,插入另一个小部件等.然后您可以免费获得滚动功能.您唯一需要担心的是配置嵌入式窗口的宽度,这并不难.

Python-子流程命令的实时输出

Python-子流程命令的实时输出

如何解决Python-子流程命令的实时输出?

你可以通过两种方法执行此操作,或者通过从readreadline函数创建迭代器,然后执行以下操作:

import subprocess
import sys
with open(''test.log'', ''w'') as f:  # replace ''w'' with ''wb'' for Python 3
    process = subprocess.Popen(your_command, stdout=subprocess.PIPE)
    for c in iter(lambda: process.stdout.read(1), ''''):  # replace '''' with b'''' for Python 3
        sys.stdout.write(c)
        f.write(c)

要么

import subprocess
import sys
with open(''test.log'', ''w'') as f:  # replace ''w'' with ''wb'' for Python 3
    process = subprocess.Popen(your_command, stdout=subprocess.PIPE)
    for line in iter(process.stdout.readline, ''''):  # replace '''' with b'''' for Python 3
        sys.stdout.write(line)
        f.write(line)

或者,你可以创建readerwriter文件。将传递writerPopen并从中读取reader

import io
import time
import subprocess
import sys

filename = ''test.log''
with io.open(filename, ''wb'') as writer, io.open(filename, ''rb'', 1) as reader:
    process = subprocess.Popen(command, stdout=writer)
    while process.poll() is None:
        sys.stdout.write(reader.read())
        time.sleep(0.5)
    # Read the remaining
    sys.stdout.write(reader.read())

这样,你就可以将数据写入test.log和标准输出中。

文件方法的唯一优点是你的代码不会被阻塞。因此,你可以同时做任何你想做的事,并reader以不阻塞的方式随时阅读。当使用PIPE,readreadline功能将阻塞,直到任一个字符被写入到管或线被分别写入到管道。

执行摘要(或“ tl; dr”版本):最多有一个很容易subprocess.PIPE,否则很难。 现在可能是时候解释一下它是如何subprocess.Popen工作的了。

(注意:这是针对Python 2.x的,尽管3.x相似;并且我对Windows变体很模糊。我对POSIX的了解要好得多。)

该Popen功能需要同时处理零到三个I / O流。分别以stdinstdout和表示stderr

你可以提供:

  • None,表示你不想重定向流。它将照常继承这些。请注意,至少在POSIX系统上,这并不意味着它将使用Pythonsys.stdout,而只是Python的实际标准输出。参见演示示例。
  • 一个int值。这是一个“原始”文件描述符(至少在POSIX中)。(旁注:PIPE和STDOUT实际上int是内部的,但是是“不可能的”描述符-1和-2。)
  • 流-实际上是具有fileno方法的任何对象。 Popen将使用来找到该流的描述符stream.fileno(),然后按照int值进行操作。
  • subprocess.PIPE,指示Python应该创建一个管道。
  • subprocess.STDOUTstderr仅适用):告诉Python使用与相同的描述符stdout。仅当你提供的(非None)值时才有意义stdout,即使如此,也只有在设置时才需要它stdout=subprocess.PIPE。(否则,你可以只提供你提供的相同参数stdout,例如Popen(..., stdout=stream, stderr=stream)。) 最简单的情况(无管道) 如果不进行任何重定向(将所有三个都保留为默认None值或提供明确的None),Pipe则非常简单。它只需要剥离子流程并使其运行。或者,如果你重定向到一个非PIPE-an int或流是fileno()-它仍然很容易,因为OS做所有的工作。Python只需要剥离子进程,即可将其stdin,stdout和/或stderr连接到提供的文件描述符。

仍然很容易的情况:一根烟斗 如果仅重定向一个流,那么Pipe事情仍然很简单。让我们一次选择一个流并观看。

假设你想提供一些stdin,但让stdout和stderr去未重定向,或去文件描述符。作为父进程,你的Python程序仅需要用于通过write()管道发送数据。你可以自己执行此操作,例如:

proc = subprocess.Popen(cmd, stdin=subprocess.PIPE)
proc.stdin.write(''here, have some data\n'') # etc

或者你可以将stdin数据传递到proc.communicate(),然后执行stdin.write上面所示的操作。没有输出返回,因此communicate()只有一项实际工作:它还会为你关闭管道。(如果不调用proc.communicate(),则必须调用proc.stdin.close()以关闭管道,以便子进程知道不再有数据通过。)

假设你想捕捉stdout,但休假stdin和stderr孤独。同样,这很容易:只需调用proc.stdout.read()(或等效命令),直到没有更多输出为止。由于proc.stdout()是普通的Python I / O流,因此可以在其上使用所有普通的构造,例如:

for line in proc.stdout:

或者,你也可以使用proc.communicate(),它可以read()为你轻松完成。

如果只想捕获stderr,则它的功能与相同stdout

在事情变得艰难之前,还有另外一个技巧。假设你要捕获stdout,并且还捕获stderr但与stdout在同一管道上:

proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

在这种情况下,subprocess“作弊”!好吧,它必须这样做,所以它并不是真正的作弊:它使用其stdoutstderr引导到(单个)管道描述符中的子进程来启动子进程,该子描述符将反馈给其父进程(Python)。在父端,只有一个管道描述符用于读取输出。所有“ stderr”输出都显示在中proc.stdout,如果调用proc.communicate(),stderr结果(元组中的第二个值)将是None,而不是字符串。

困难的情况:两个或多个管道 当你要使用至少两个管道时,所有问题都会出现。实际上,subprocess代码本身具有以下功能:

def communicate(self, input=None):
    ...
    # Optimization: If we are only using one pipe, or no pipe at
    # all, using select() or threads is unnecessary.
    if [self.stdin, self.stdout, self.stderr].count(None) >= 2:

但是,可惜,在这里,我们至少制作了两个(也许三个)不同的管道,因此count(None)返回值为1或0。我们必须用困难的方式做事。

在Windows上,这用于threading.Thread累积self.stdout和的结果self.stderr,并让父线程传递self.stdin输入数据(然后关闭管道)。

在POSIX上,poll如果可用,则使用,否则select,使用累加输出并传递标准输入。所有这些都在(单个)父进程/线程中运行。

这里需要线程或轮询/选择以避免死锁。例如,假设我们已将所有三个流重定向到三个单独的管道。进一步假设在写入过程被挂起之前,等待读取过程从另一端“清除”管道之前,可以在管道中填充多少数据有一个很小的限制。让我们为单个字节设置一个小的限制。(实际上,这是工作原理,但限制远大于一个字节。)

如果父(Python)进程尝试写入多个字节,例如''go\n''到proc.stdin,则第一个字节进入,然后第二个字节导致Python进程挂起,等待子进程读取第一个字节,从而清空管道。

同时,假设子流程决定打印一个友好的“ Hello!Do n''t Panic!”。问候。在H进入它的标准输出管道,但e导致其暂停,等待其家长阅读H,排空stdout管道。

现在我们陷入困境:Python进程正在睡眠,等待说完“ go”,而子进程也处于睡眠状态,等待说完“ Hello!Don Panic!”。

subprocess.Popen代码避免了线程化或选择/轮询的问题。当字节可以通过管道时,它们就会通过。如果不能,则只需要一个线程(而不是整个进程)就可以进入睡眠状态;或者,在进行选择/轮询的情况下,Python进程同时等待“可以写入”或“可用数据”,然后写入该进程的stdin仅在有空间时,并且仅在数据准备好时读取其stdout和/或stderr。一旦发送完所有stdin数据(如果有的话)并且所有stdout和/或stderr数据都已存储,该proc.communicate()代码(实际上_communicate是处理多毛案件的地方)将返回。

如果你想同时读取stdoutstderr在两个不同的管道(无论任何的stdin重定向),则需要避免死锁了。此处的死锁情况有所不同-发生在子进程stderr从中提取数据时写入了很长时间stdout,反之亦然,但是这种情况仍然存在。

演示 我答应演示未经重定向的python subprocess写入底层标准输出,而不是sys.stdout。所以,这是一些代码:

from cStringIO import StringIO
import os
import subprocess
import sys

def show1():
    print ''start show1''
    save = sys.stdout
    sys.stdout = StringIO()
    print ''sys.stdout being buffered''
    proc = subprocess.Popen([''echo'', ''hello''])
    proc.wait()
    in_stdout = sys.stdout.getvalue()
    sys.stdout = save
    print ''in buffer:'', in_stdout

def show2():
    print ''start show2''
    save = sys.stdout
    sys.stdout = open(os.devnull, ''w'')
    print ''after redirect sys.stdout''
    proc = subprocess.Popen([''echo'', ''hello''])
    proc.wait()
    sys.stdout = save

show1()
show2()

运行时:

$ python out.py
start show1
hello
in buffer: sys.stdout being buffered

start show2
hello

请注意,如果添加stdout=sys.stdout,第一个例程将失败,因为StringIO对象没有fileno。第二个将省略hello如果添加stdout=sys.stdout,因为sys.stdout已被重定向到os.devnull。

(如果重定向Python的file-descriptor-1,则子进程将遵循该重定向。该open(os.devnull, ‘w’)调用将产生一个fileno()大于2 的流。)

解决方法

我正在使用python脚本作为水动力代码的驱动程序。是时候运行模拟了,我subprocess.Popen用来运行代码,将stdoutstderr的输出收集到subprocess.PIPE---中,然后我可以打印(并保存到日志文件中)输出信息,并检查是否有错误。问题是,我不知道代码是如何进行的。如果我直接从命令行运行它,它将为我提供有关其迭代次数,时间,下一时间步长等的输出。

有没有办法既存储输出(用于日志记录和错误检查),又产生实时流输出?

我的代码的相关部分:

ret_val = subprocess.Popen( run_command,stdout=subprocess.PIPE,stderr=subprocess.PIPE,shell=True )
output,errors = ret_val.communicate()
log_file.write(output)
print output
if( ret_val.returncode ):
    print "RUN failed\n\n%s\n\n" % (errors)
    success = False

if( errors ): log_file.write("\n\n%s\n\n" % errors)

最初,我是run_command通过管道传递tee文件,以便将副本直接发送到日志文件,并且流仍直接输出到终端-但是那样,我无法存储任何错误(据我所知)。

编辑:

临时解决方案:

ret_val = subprocess.Popen( run_command,stdout=log_file,shell=True )
while not ret_val.poll():
    log_file.flush()

然后,在另一个终端中,运行tail -f log.txt(st log_file = ''log.txt'')

Python:Tkinter小部件背景(按钮,条目等)

Python:Tkinter小部件背景(按钮,条目等)

我在创建GUI时遇到了一些问题.这是在改变背景时,我可以改变整个背景,也可以改变标签等的背景,但是当涉及按钮和输入字段等时,按钮后面有一个白色区域,我似乎无法改变:S

问题可以在下面的图片中看到.

(没有足够的声誉来张贴图片,所以会链接它)
http://www.thesite.dk/upload/media/tkinter.png

随着代码:

from Tkinter import *

background = "BLACK"
textColor = "WHITE"
root = Tk()
root.configure(bg=background)

Email = Label(root,text="Enter E-mail Address :",font=("Lucida Grande",12),fg=textColor,background=background)
Email.grid(row=6,column=0,sticky=NW,padx=19)

EmailField = Entry(root,width=30)
EmailField.grid(row=6,columnspan=3,padx=159)

EmailButton = Button(root,text="Mail It !",background=background)
EmailButton.grid(row=6,columnspan=6,padx=389)

SM_Status = StringVar()
EmailStatus = Label(root,textvariable=SM_Status,background=background)
EmailStatus.grid(row=6,column=2,padx=20)

可能有一个简单的解决方案,但无数的谷歌和几个小时的阅读文档和论坛帖子让我无处可去:(我希望你能帮助…

是的,我正在使用Mac OS X和python 2.6

最佳答案
我知道已经有一段时间了,你肯定不再研究这个代码,但我找到了一个解决方案,我会在这里发布给每个有类似问题的人.这与将条目周围的区域作为背景颜色的方式相同:

highlightbackground =颜色

Raspberry Pi-如何通过HDMI显示某些TKinter小部件-在VNC上运行另一个小部件时

Raspberry Pi-如何通过HDMI显示某些TKinter小部件-在VNC上运行另一个小部件时

如何解决Raspberry Pi-如何通过HDMI显示某些TKinter小部件-在VNC上运行另一个小部件时?

我有一个RaspBerry PI,它从我的VNC“无头”运行。同时将其连接到监视器/电视屏幕。

我希望运行python-Tkinter GUI,它有两个按钮可以启动/停止PC / VNC上的特定循环。同时,我希望RaspBerry Pi在屏幕上/通过HDMI在屏幕上显示计时器Tkinter GUI。

这可能吗?我知道,如果我有两个监视器,则可以将窗口小部件放置在“ -x”和“ -y”平面中,这将导致该窗口小部件显示在主屏幕/监视器之外。

我能否以某种方式欺骗RaspBerry Pi,使我的VNC成为第二台显示器?

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

关于在Tkinter小部件中显示子流程的实时输出利用tkinter模块中的子模块的问题我们已经讲解完毕,感谢您的阅读,如果还想了解更多关于python – 在Tkinter中滚动一组小部件、Python-子流程命令的实时输出、Python:Tkinter小部件背景(按钮,条目等)、Raspberry Pi-如何通过HDMI显示某些TKinter小部件-在VNC上运行另一个小部件时等相关内容,可以在本站寻找。

本文标签: