返回Python中的连续终端日志

返回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

我正在创建一个小应用程序,我可以插入我的android手机的IP地址,然后只需按一个按钮。我通过ADB进行无线连接。这是可行的,现在我想在一个可滚动的、不可编辑的文本字段中显示
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循环永远无法恢复控制。这就是它冻结的原因

一般来说,一个人可以做几件事:

  • 定期进行非阻塞呼叫。 换句话说:主循环需要定期调用非阻塞函数,该函数返回任何输出(如果有)
  • 将任何阻塞代码移动到单独的线程
  • 使用asyncio(我不会给你举一个这样的例子)
  • #1:在不阻塞的情况下读取日志的想法符合#1您需要实现定期调用的逻辑

    #2:如果将读取循环移动到线程,则可以释放主线程来执行其他任何操作并做出响应。然后让logcatresult线程填充滚动文本。在这种情况下,你甚至不需要我上面提到的东西

    以下是可能适合您的简化版本:

    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()
      。否则,在进程结束之前,您的程序将不会退出

    为什么打印永远不会结束?也包括您的tkinter代码,这样我们可以帮助Better。ADB Logcat是一个命令,您可以在其中显示连接的android设备的设备信息。这是实时的,只报告当前状态。仅当设备断开连接、命令停止或给定特定时间时,此操作才会停止。我希望它显示设备信息,只要它连接。我将在文章中添加一些logcat中的示例行。可能有很多原因导致这种情况发生,为了更好地理解,您可以展示更多的代码吗?关于执行整个函数的部分,请注意,我没有回答如何实际显示日志,而是关于冻结。它们实际上是两个不同的问题。所以你决定哪一个是真正的问题。一旦你有了非阻塞功能,它就可以添加到你决定显示信息的任何小部件中。非常感谢,通过使用你发布的第一个链接和第二个答案,我可以在控制台中打印输出。但当试图在文本窗口中设置值时,应用程序仍然冻结。编辑:或者只是在一般情况下它仍然冻结,但我现在可以打印出来。我将在帖子中添加代码,并再次编辑答案。我建议:1.-更改标题(这是关于在不阻塞GUI的情况下从子进程读取stdout)。也许有人有更好的标题建议。2.-更改标签(例如:这与android无关)3.-它也与您如何在Tk中显示它无关(至少,这可以分为两个问题,一个关于GUI冻结,一个关于更新小部件)。如果这对您有效,我将用最终版本编辑答案。