简体   繁体   English

使用 Popen 将 Python 变量传递给 Powershell 参数

[英]Passing Python variable to Powershell parameter using Popen

Got one for ya...给你一个...

I am calling Powershell scripts from within my Python code, using Python's subprocess.Popen ;我正在使用 Python 的subprocess.Popen从我的 Python 代码中调用 Powershell 脚本; there's one Powershell script that requires an initial input parameter, and then an 'Enter' at the end, to quit.有一个 Powershell 脚本需要一个初始输入参数,然后在最后输入“Enter”才能退出。 This one is giving me some trouble;这个给我带来了一些麻烦; Powershell code goes a little something like this: Powershell 代码有点像这样:

$usrFileName = read-host "Please enter a file name to save the report"
*does some computering*
*creates some output* #ideally looking to capture this to output, but not the main problem
#display task complete to user
Read-Host -Prompt "Press Enter to exit" #This is problematic - don't know how to end this

Python code:蟒蛇代码:

from tkinter import *
import os, datetime
import subprocess
from subprocess import Popen, PIPE
from keyboard import press_and_release


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

frame = Frame(window)

fldrPath = r"C:/Users/paul.sisson/Downloads/Powershell Development/Monthly PMs PowerShell scans/BLDG-7UP-SUNY-Scans/7UP-LAB-A-325/"

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

# Get todays date and add the lab name to be piped later
today = (datetime.datetime.now().strftime('%d%b%Y')).upper()
usrFileName = today + "-7UP-A-325"

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

def selection():
    fileList = listbox.curselection()
    for file in fileList:
        keyword = 'Scans'
        os.chdir(fldrPath)

        proc = subprocess.Popen(["powershell.exe", '-File', fldrPath + '\\' + listbox.get(file)], bufsize=0,
                                universal_newlines=1, stdout=subprocess.PIPE, stdin=subprocess.PIPE)

        #proc.stdin.write(usrFileName) works to name file, but then deadlocks
   
        while proc.poll() is None:
            p = proc.stdout.readline()
            output.insert('end', p)
            output.update()


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()

I've successfully passed the input, using proc.stdin.write(usrFileName) , but I'm worried it's not the proper way to go about it.我已经使用proc.stdin.write(usrFileName)成功传递了输入,但我担心这不是正确的方法。 Considering the fact that I want to read AND write, I don't want to risk deadlocking the process, which I'm pretty sure is happening.考虑到我想读和写的事实,我不想冒险使进程陷入僵局,我很确定这种情况正在发生。

Tried a few other examples, based on a few threads:根据几个线程尝试了其他一些示例:

proc = subprocess.Popen(["powershell.exe", '-File', fldrPath + '\\' + listbox.get(file),'-usrFileName:',
                                         propername], bufsize=0, universal_newlines=1, 
                                         stdout=subprocess.PIPE, stdin=subprocess.PIPE)

went with subprocess.call once or twice but I need to use proc.poll for the output, so that won't work.与去subprocess.call一次或两次,但我需要使用proc.poll的输出,这样就不会工作。

You can see that I brought in keyboard to remedy the enter, but code would hang before getting there, so not sure if that's the way to go.你可以看到我带来了keyboard来补救回车,但是代码会在到达那里之前挂起,所以不确定这是否是要走的路。

Long story short - I'm looking for some guidance on properly writing usrFileName to Powershell, at the beginning, reading the output from the Powershell, and then executing the 'Press Enter', at the end.长话短说- 我正在寻找一些指导,以正确地将usrFileName写入 Powershell,在开始时,从 Powershell 读取输出,然后在最后执行“按 Enter”。

Should I explicitly close stdin , so the child process stops hanging?我应该明确关闭stdin ,以便子进程停止挂起吗?

I'm feeling like .communicate() or threading is the way to go, but I need someone with some elegance to show me the way!我觉得.communicate()或线程是要走的路,但我需要一些优雅的人来给我指路!

Appreciate the support.感谢支持。

PS Changing the Powershell isn't an option, not my code, just trying to work with something that's already in place. PS 更改 Powershell 不是一个选项,不是我的代码,只是尝试使用已经存在的东西。 Thanks!谢谢!

Answering interactive Read-Host prompts via stdin requires that each response be terminated with a newline .通过 stdin 回答交互式Read-Host提示要求每个响应都以换行符终止。

Therefore, end your stdin input with 2 newlines: one to answer the filename prompt, and another to answer the exit prompt:因此,用2 个换行符结束 stdin 输入:一个用于回答文件名提示,另一个用于回答退出提示:

proc.stdin.write(usrFileName + '\n\n')

Note : PowerShell's stdout output will also include the prompt message and the response submitted, so you need to account for that when you parse the output;注意:PowerShell 的 stdout 输出也将包括提示信息和提交的响应,因此您在解析输出时需要考虑到这一点; specifically, stdout output will include the following:具体来说,stdout 输出将包括以下内容:
Please enter a file name to save the report: 10Sep2020--7UP-A-325 (for instance), Press Enter to exit: , plus an extra empty line, because the exit prompt's Read-Host statement's output isn't captured in a variable and is therefore implicitly output. Please enter a file name to save the report: 10Sep2020--7UP-A-325 (例如), Press Enter to exit: ,加上一个额外的空行,因为退出提示的Read-Host语句的输出没有被捕获变量,因此是隐式输出。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM