我尝试过使用我在网上找到的几种不同的类似解决方案,但似乎没有一种方法可以完全实现我的目标。
我想将一个外部脚本(helloworld.py)调用到我的tkinter gui中。我希望这个名为脚本(helloworld.py)的函数在gui中按下按钮时执行其中包含的所有函数,并将结果输出打印到gui中,而不是控制台。我找到了一些解决方案,将输出打印到控制台,但我无法让它显示在gui中。当我试图让输出来自一个被调用的外部脚本时,我发现打印到gui的任何解决方案都不起作用。
我感谢任何帮助。我绝对是一个新手,所以我为可能是一个基本问题而道歉,并且无法在这里提出的类似问题上为自己连接点。下面是我目前正在使用的代码版本之一。提前感谢您的帮助!
import Tkinter
import sys
import subprocess
sys.path.append('/users/cmbp')
def callback():
import os
print subprocess.call('python /users/cmbp/p4e/helloworld.py',
shell=True)
lbl = Tkinter.Label(master)
lbl.pack()
master = Tkinter.Tk()
master.geometry('200x90')
master.title('Input Test')
Btn1 = Tkinter.Button(master, text="Input", command=callback)
Btn1.pack()
master.mainloop()
修改
我也开始尝试将被调用的脚本作为模块导入。这个问题是我只能从被调用的脚本中打印出一个函数,即使我想尝试和调用多个函数(我只是希望整个被调用的脚本打印出其函数的所有结果)。
以下是我想调用helloworld.py的脚本示例:
def cooz():
return ('hello worldz!')
def tooz():
return ("here is another line")
def main():
return cooz()
return tooz()
以下是尝试导入helloworld.py的tkinter gui脚本示例:
import Tkinter as tk
import helloworld
def printSomething():
y = helloworld.main()
label = tk.Label(root, text= str(y))
label.pack()
root = tk.Tk()
root.geometry('500x200')
root.title('Input Test')
button = tk.Button(root, text="Print Me", command=printSomething)
button.pack()
root.mainloop()
这导致只有第一个函数打印('hello worldz!')。有关为什么它只会返回一行而不是整个helloworld.py脚本的任何想法?
答案 0 :(得分:2)
您可以使用subprocess.check_output()
获取输出并分配到Label
您还可以import
脚本并从脚本执行函数。
import test
test.function()
但首先,您必须使用sys.stdout
类重定向write()
,然后它将捕获所有打印文本。
您可以将sys.stdout
重定向到变量(请参阅StdoutRedirector
),然后您可以对其进行编辑(即最后为条带\n
),也可以直接重定向到Label
(见StdoutRedirectorLabel
)
import Tkinter as tk
# -----
import subprocess
def callback1():
cmd = 'python test.py'
# it will execute script which runs only `function1`
output = subprocess.check_output(cmd, shell=True)
lbl['text'] = output.strip()
# -----
class StdoutRedirector(object):
def __init__(self):
# clear before get all values
self.result = ''
def write(self, text):
# have to use += because one `print()` executes `sys.stdout` many times
self.result += text
def callback2():
import test
# keep original `sys.stdout
old_stdout = sys.stdout
# redirect to class which has `self.result`
sys.stdout = StdoutRedirector()
# it will execute only `function2`
test.function2()
# assign result to label (after removing ending "\n")
lbl['text'] = sys.stdout.result.strip()
# set back original `sys.stdout
sys.stdout = old_stdout
# -----
import sys
class StdoutRedirectorLabel(object):
def __init__(self, widget):
self.widget = widget
# clear at start because it will use +=
self.widget['text'] = ''
def write(self, text):
# have to use += because one `print()` executes `sys.stdout` many times
self.widget['text'] += text
def callback3():
import test
# keep original `sys.stdout
old_stdout = sys.stdout
# redirect to class which will add text to `lbl`
sys.stdout = StdoutRedirectorLabel(lbl)
# it will execute only `function3` and assign result to Label (with ending "\n")
test.function3()
# set back original `sys.stdout
sys.stdout = old_stdout
# --- main ---
master = tk.Tk()
master.geometry('200x200')
lbl = tk.Label(master, text='')
lbl.pack()
btn1 = tk.Button(master, text="subprocess", command=callback1)
btn1.pack()
btn2 = tk.Button(master, text="StdoutRedirector", command=callback2)
btn2.pack()
btn3 = tk.Button(master, text="StdoutRedirectorLabel", command=callback3)
btn3.pack()
master.mainloop()
test.py
def function1():
print('function 1')
def function2():
print('function 2')
def function3():
print('function 3')
if __name__ == '__main__':
function1()
答案 1 :(得分:1)
在运行return ...
行的方法中,在该行之后将看不到任何其他内容,因为return ...
的第二行实际上没用,因为return cooz()
是无条件地运行 。您只需将main
替换为:
def main():
return cooz(), tooz()
并据此printSomething
:
x, y = helloworld.main()
嗯,我stand corrected,基于this answer你可以相当简单地做到。对于调用所有方法或函数this answer有很多帮助。
假设有一个名为hello_world.py
的脚本:
def hello_world():
print("Hello World!")
print("this is the 2nd line of this method")
def multiplication(*args):
mult = 1
for arg in args:
mult *= arg
return mult
def some_other_method():
print("some other method")
print(multiplication(2, 3, 5, 7))
位于以下GUI脚本的相同的目录中:
import tkinter as tk # required for the GUI
import subprocess # required for redirecting stdout to GUI
import sys, inspect # required for all methods and functions redirection
import hello_world # the script file that is redirected
def redirect(module, method):
'''Redirects stdout from the method or function in module as a string.'''
proc = subprocess.Popen(["python", "-c",
"import " + module.__name__ + ";" + module.__name__ + "." + method + "()"],
stdout=subprocess.PIPE)
out = proc.communicate()[0]
return out.decode('unicode_escape')
def redirect_module(module):
'''Retruns all stdout from all methods or functions in module as a string.'''
# to filter out non-method, and non-function attributes
all_mtds_or_funcs = inspect.getmembers(sys.modules[module.__name__],
inspect.isfunction or inspect.ismethod)
red_str_buffer = ""
for method in all_mtds_or_funcs:
red_str_buffer += redirect(module, method[0]) + "\n---\n"
return red_str_buffer
def put_in_txt(module):
'''Puts the redirected string in a text.'''
txt.insert('1.0', redirect_module(module))
root = tk.Tk()
txt = tk.Text(root)
btn = tk.Button(root, text="Redirect")
btn['command'] = lambda module=hello_world : put_in_txt(module)
txt.pack()
btn.pack()
root.mainloop()
以hello_world.py
作为字符串返回所有方法和函数的控制台输出。根据{{3}},然后将该字符串放在this suggestion字段中。