Python - 读取 Powershell 脚本输出,使用子进程,希望逐行接收标准输出

Pau*_*son 5 python powershell tkinter python-3.x

一直试图从运行了一点的 Powershell 脚本读取标准输出,根据它正在 ping 的计算机数量生成输出。

试图让数据流入文本框,但毕竟我已经尝试过了,我似乎只能让它一次提供所有输出。

一直试图不使用subprocess.communicate(),因为它似乎也一次提供所有输出。

这是代码:

from tkinter import *
import os
from subprocess import Popen, PIPE


window = Tk()
window.title( 'PowerShell Script Temp' )

frame = Frame(window)

fldrPath = r"C:/Users/firstname.lastname/Downloads/Powershell Development/Monthly Scans/"

listbox = Listbox(frame)
listbox.configure(width=50)

for name in os.listdir(fldrPath):
    listbox.insert('end', name)

def selection():
    fileList = listbox.curselection()
    for file in fileList:
        os.chdir(fldrPath)
        
        # Right here is the problematic section
        with Popen(["powershell.exe", '-File', fldrPath + '\\' + listbox.get(file)], stdout=PIPE, bufsize=1,
                   universal_newlines=True) as p:
            for line in p.stdout:
                output.insert('end', line)
                print(line, end='')   

output = Text(window, width=75, height=6, wrap=WORD, background="white")

btn = Button(frame, text='Run Script', command=selection)

btn.pack(side=RIGHT, padx=5)
listbox.pack(side=LEFT)
frame.pack(padx=30, pady=30)
output.pack(fill=BOTH, expand=1, padx=5, pady=5)

window.mainloop()
Run Code Online (Sandbox Code Playgroud)

不逐行过滤- 只是在 PS 脚本完成后将其全部吐出。

我已经尝试了很多其他的事情:

尝试 1

proc = subprocess.Popen(["powershell.exe", '-File', fldrPath + '\\' + listbox.get(file)], shell=True, stdout=PIPE)
    while proc.poll() is None:
         data = proc.stdout.readline()  # Alternatively proc.stdout.read(1024)
         print(data)
         text_box.insert('end', data)
Run Code Online (Sandbox Code Playgroud)

尝试 2

outpipe = subprocess.Popen(["powershell.exe", '-File', fldrPath + '\\' + listbox.get(file)],
                                stdin=subprocess.PIPE,
                                stdout=subprocess.PIPE,
                                stderr=subprocess.PIPE).communicate()[0]
    text_box.insert("end", outpipe)
Run Code Online (Sandbox Code Playgroud)

尝试 3

with Popen(["powershell.exe", '-File', fldrPath + '\\' + listbox.get(file)], stdout=PIPE, bufsize=1,
         universal_newlines=True) as p, StringIO() as buf:
         for line in p.stdout:
             print(line, end='')
             buf.write(line)
         outpipe = buf.getvalue()
         output.insert('end', outpipe)
Run Code Online (Sandbox Code Playgroud)

尝试 4

proc = subprocess.Popen(["powershell.exe", '-File', fldrPath + '\\' + listbox.get(file)], shell=True,
                             stdout=subprocess.PIPE)
     while proc.poll() is None:
         p = proc.stdout.readline()
         output.insert('end', p)
Run Code Online (Sandbox Code Playgroud)

我实际上尝试了更多,但似乎无法记住它们。很多 fors 和 withs ......我现在有点厌倦了。我可以Print()以我想要的方式得到这个东西,但不能流入文本框;几乎就像.insert()是太慢了。

如果有人能将我引向正确的方向,我将不胜感激。在这里尝试了几乎所有我可以管理的类似线程,只是似乎没有成功。

Atl*_*435 1

尝试让数据流入文本框,但在我尝试过之后,我似乎只能让它一次给出所有输出。

这段代码在这里:

def selection():
    fileList = listbox.curselection()
    for file in fileList:
        os.chdir(fldrPath)
        
        # Right here is the problematic section
        with Popen(["powershell.exe", '-File', fldrPath + '\\' + listbox.get(file)], stdout=PIPE, bufsize=1,
                   universal_newlines=True) as p:
            for line in p.stdout:
                output.insert('end', line)
                print(line, end='') 
Run Code Online (Sandbox Code Playgroud)

被执行,完成后你可以看到它做了什么。要更新它,您可以使用aftertkinter 的方法并检查给定时间内的更改。就像这里的例子一样。

tkinter 主循环的工作原理如下

     Start
       |
       |<----------------------------------------------------------+
       v                                                           ^
   Do I have    No[*]  Calculate how            Sleep for at       |
   work to do?  -----> long I may sleep  -----> most that much --->|
       |                                        time               |
       | Yes                                                       |
       |                                                           |
       v                                                           |
   Do one callback                                                 |
       |                                                           |
       +-----------------------------------------------------------+
Run Code Online (Sandbox Code Playgroud)

另一个建议是使用另一个线程您还应该阅读此处的答案.communicate()