从Python运行命令,然后关闭
我想构建一个小的shell应用程序,它从GUI应用程序运行一个命令。当我按下“关闭”按钮时,该命令的控制台应该关闭。我有两个问题:从Python运行命令,然后关闭
当我运行该命令时,该命令在与我的Python脚本相同的控制台上运行。我如何在新的控制台中打开命令?
如何停止命令?我的意思是,如果该命令与GUI的工作过程相同,我可以使用
exit()
,但是整个程序将终止。
这是我到目前为止的代码:
from tkinter import *
import subprocess
import os
top = Tk()
def turnOn():
p = subprocess.Popen("ping *.com")
def turnOff():
pass
#should i do: p.close() of something?
on = Button(top, text = "on", command = turnOn)
off = Button(top, text = "off", command = turnOff)
on.grid()
off.grid()
top.mainloop()
您可以通过调用子进程的.terminate
方法停止命令。下面是一个粗略的例子,它使用全局变量来存储Popen
对象;将GUI包装在一个类中会更好,并将proc
作为该类的实例属性存储。
import tkinter as tk
import subprocess
top = tk.Tk()
proc = None
def turnOn():
global proc
if proc is None:
print('Starting ping')
proc = subprocess.Popen(["ping", "example.com"])
def turnOff():
global proc
if proc is not None:
print('Stopping ping')
proc.terminate()
proc = None
on = tk.Button(top, text = "on", command = turnOn)
off = tk.Button(top, text = "off", command = turnOff)
on.grid()
off.grid()
top.mainloop()
的if proc is None:
线防止ping
命令被重新启动,如果它已经运行。
是的,但如果我在新控制台中执行命令,如:subprocess.Popen(command,creationflags = subprocess.CREATE_NEW_CONSOLE),则proc.terminate()将不会关闭新控制台。 – odri
@odri好的。 (我无法测试,因为我不使用Windows)。但为什么你真的需要在新的控制台上运行? –
1)当我运行命令时,cmd命令运行在与我的 pythoh脚本工作相同的cmd上。我怎样才能打开另一个cmd窗口中的命令?
我假设您试图说您需要在另一个 shell上运行该进程。您应该使用的子功能的“壳”参数:
subprocess.call(cmd, shell=True)
相反,如果你只需要另一个命令提示符窗口,只是POPEN另一个Windows CMD。
2)如何停止命令?我的意思是,如果命令是在同一个 窗口上工作的,我可以在exit()中使用gui工作,但是所有程序将会停止。
子过程Popen对象有一个终止方法。你可以调用这个发送一个SIGTERM信号,但并不总是可靠的。因此,有从您的操作系统和您的过程 的性质取决于几个选项(一张小纸条:POPEN对象与进程的PID一个PID属性):
- os.kill(PID,信号) =>杀上的Posix/Windows操作系统
- os.killpg(PGID,信号) =>一个简单的过程杀死一个进程作为在Unix操作系统
- 子的基团。POPEN( “TASKKILL/F/T/PID%i” 的%PID,壳=真) =>杀上的窗口的处理
信号是从OS根据一个POSIX /窗口信号。即:
os.killpg(self.pid, signal.SIGKILL) # Posix
os.kill(self.pid, signal.CTRL_C_EVENT) # Windows
os.kill调用在Windows上并不总是可靠的。这是使用第三个选项的原因 。
CMD不是控制台;它执行REPL就像python.exe在交互式运行时一样。命令行shell或REPL从标准输入读取并写入标准输出和标准错误。它没有实现它们,它不知道任何有关窗口,窗口消息,鼠标输入等。产生一个新的cmd.exe实例继承当前的控制台。要创建一个新的控制台(即conhost.exe的实例),请使用创建标志CREATE_NEW_CONSOLE。除非需要运行批处理文件或使其执行命令行,否则CMD不涉及此问题。 – eryksun
Windows没有信号。 Python在Windows上的'os.kill()'实现是一个混合函数。在一个层面上,它就像'os.killpg'一样。如果您连接到与子进程相同的控制台,并且您使用'CREATE_NEW_PROCESS_GROUP'创建了进程,即其进程ID也是进程组ID,则可以向其发送控制台控制事件,即'CTRL_C_EVENT'(0 )或'CTRL_BREAK_EVENT'(1),但Ctrl + C默认是禁用的,所以只有Ctrl + Break是可靠的。这称为WinAPI'GenerateConsoleCtrlEvent'。传递不是进程组ID的ID是未定义的行为。 – eryksun
将控件事件发送到进程组0将事件广播到连接到控制台的所有进程,包括您自己的进程。 – eryksun
你有没有尝试cmd的选项,例如''cmd/c“ping *.com”''? – Gribouillis
最初的问题与控制台混淆了CMD。我没有看到任何与CMD外壳相关的东西,所以我编辑它来专注于控制台。使用参数'creationflags = subprocess.CREATE_NEW_CONSOLE'可以很容易地获得一个新的控制台。 – eryksun