返回Python中的连续终端日志
我正在创建一个小应用程序,我可以插入我的android手机的IP地址,然后只需按一个按钮。我通过ADB进行无线连接。这是可行的,现在我想在一个可滚动的、不可编辑的文本字段中显示返回Python中的连续终端日志,python,android,python-3.x,tkinter,logcat,Python,Android,Python 3.x,Tkinter,Logcat,我正在创建一个小应用程序,我可以插入我的android手机的IP地址,然后只需按一个按钮。我通过ADB进行无线连接。这是可行的,现在我想在一个可滚动的、不可编辑的文本字段中显示adb logcat的日志。但是在这里我遇到了一个问题,我试图像这样捕获logcat命令的输出p=os.popen(“adb logcat”),然后像这样打印它print(p.read())。这只会使我的应用程序(tkinter)冻结,我猜这与打印永远不会结束这一事实有关。有人知道如何显示logcat结果吗 功能代码 de
adb logcat
的日志。但是在这里我遇到了一个问题,我试图像这样捕获logcat命令的输出p=os.popen(“adb logcat”)
,然后像这样打印它print(p.read())
。这只会使我的应用程序(tkinter)冻结,我猜这与打印永远不会结束这一事实有关。有人知道如何显示logcat结果吗
功能代码
def logcatcommand():
p = os.popen("adb logcat")
print(p.read())
按钮:
button2 = tk.Button(text="Open logcat",width=25, height=3, command=logcatcommand)
button2.grid(row=5, column=0)
你们对我如何实时显示这些信息也有想法吗?我想我必须使用这样的代码:
result = scrolledtext.ScrolledText(window, wrap = tk.WORD, width = 40, height = 10, font = ("Times New Roman", 15))
result.grid(column = 1, row=0)
result.insert(tk.INSERT, output)
result.configure(state ='disabled')
其中输出是从终端检索到的实时数据
采样线logcat:
09-10 14:10:28.479 971 3009 I WifiHAL : event received NL80211_CMD_VENDOR, vendor_id = 0x1374, subcmd = 0xd
09-10 14:10:34.779 1526 4567 I BatteryStatsService: In wakeup_callback: resumed from suspend
09-10 14:10:35.321 1526 4567 I BatteryStatsService: In wakeup_callback: suspend aborted
编辑:
多亏了Javier Gonzalez,我能够使用以下方式打印日志:
def logcatcommand():
popen = subprocess.Popen(args="adb logcat", shell=True, stdout=subprocess.PIPE)
return iter(popen.stdout.readline, b"")
def logcatresult():
for line in logcatcommand():
print(line)
但是,当尝试将值设置为变量或只是执行其他操作(如尝试按下另一个按钮)时,我唯一看到的是MacOSX中的彩虹纺车
格里茨我相信这里的提问方式略有不同: 在您的代码中,我实际使用的是子流程模块,而不是os.popen 当我第一次遇到这个问题时,我使用了我在上面链接的问题的答案中提到的模块。更现代的方法是使用asyncio。这里的问题是使用asyncio的方法多种多样,您可以在SO中找到这些方法。由于asyncio在不同的版本中发生了显著的变化,所以它们有所不同 编辑#1 潜在的问题是主线程阻塞。现在,在logcatresult函数中有一个永远不会结束的循环,因此它永远不会返回。Tk循环永远无法恢复控制。这就是它冻结的原因 一般来说,一个人可以做几件事:
from tkinter import *
from tkinter import messagebox
import threading
import subprocess
THREAD = None
PROCESS = None
def read_log(process):
for line in iter(process.stdout.readline, b""):
print(line.decode(), end=''),
def read_log_thread():
""" Button-Event-Handler starting the log reading. """
global THREAD
global PROCESS
PROCESS = subprocess.Popen(["adb logcat"], shell=False, stdout=subprocess.PIPE)
THREAD = threading.Thread(target=read_log, args=(PROCESS,))
THREAD.start()
def hello():
messagebox.showinfo(message='Hello.')
def main():
root = Tk()
Button(master=root, text='Start reading', command=read_log_thread).pack()
buttonX = Button(master=root, text='Hello', command=hello).pack()
root.mainloop()
if PROCESS and PROCESS.poll():
PROCESS.terminate()
THREAD.join()
if __name__ == '__main__':
main()
要记住的事情:
- 这个实现只是一个指南。它将有一些问题(下面提到)
- 我会尽量不使用globals
- 您需要确保在最后(所有子进程结束、线程结束等)正确清理所有内容
- 没有什么可以阻止您按两次按钮,创建多个(泄漏的)线程和进程,因为变量是全局的,不进行任何检查
- 还要注意,我使用了
,因此我可以shell=False
。否则,在进程结束之前,您的程序将不会退出PROCESS.terminate()