【发布时间】:2014-01-13 16:29:05
【问题描述】:
总结
我有 wxPython GUI,它允许用户打开文件进行查看。目前我用os.startfile() 做这个。但是,我了解到这不是最好的方法,所以我正在寻求改进。 startfile() 的主要缺点是文件一旦启动,我就无法控制它。这意味着用户可以将文件保持打开状态,因此其他用户将无法使用该文件。
我在寻找什么
在我的 GUI 中,可以有子窗口。我通过将 GUI 对象存储在一个列表中来跟踪所有这些,然后当父级关闭时,我只需遍历列表并关闭所有子级。我想对用户选择的任何文件做同样的事情。如何启动一个文件并保留一个 python 对象,以便我可以按命令关闭它?在此先感谢
我的解决方案梦想
- 以这样一种方式启动文件,即有一个我可以在函数之间传递的 Python 对象
- 在默认程序中启动文件并返回 PID 的某种方式
- 一种使用文件名检索 PID 的方法
目前的进展
这是我计划使用的框架。重要的位是FileThread 类的run() 和end() 函数,因为这是解决方案的所在。
import wx
from wx.lib.scrolledpanel import ScrolledPanel
import threading
import os
class GUI(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, -1, 'Hey, a GUI!', size=(300,300))
self.panel = ScrolledPanel(parent=self, id=-1)
self.panel.SetupScrolling()
self.Bind(wx.EVT_CLOSE, self.OnClose)
self.openFiles = []
self.openBtn = wx.Button(self.panel, -1, "Open a File")
self.pollBtn = wx.Button(self.panel, -1, "Poll")
self.Bind(wx.EVT_BUTTON, self.OnOpen, self.openBtn)
self.Bind(wx.EVT_BUTTON, self.OnPoll, self.pollBtn)
vbox = wx.BoxSizer(wx.VERTICAL)
vbox.Add((20,20), 1)
vbox.Add(self.openBtn)
vbox.Add((20,20), 1)
vbox.Add(self.pollBtn)
vbox.Add((20,20), 1)
hbox = wx.BoxSizer(wx.HORIZONTAL)
hbox.Add(vbox, flag=wx.TOP|wx.BOTTOM|wx.LEFT|wx.RIGHT|wx.EXPAND, border = 10)
self.panel.SetSizer(hbox)
self.panel.Layout()
def OnOpen(self, event):
fileName = "AFileIWantToOpenWithTheFullPath.txt"
self.openFiles.append(FileThread(fileName))
def OnPoll(self, event):
self.openFiles[0].Poll()
def OnClose(self, event):
for file in self.openFiles:
file.end()
self.openFiles.remove(file)
self.Destroy()
class FileThread(threading.Thread):
def __init__(self, file):
threading.Thread.__init__(self)
self.file = file
self.start()
def run(self):
doc = subprocess.Popen(["start", " /MAX", "/WAIT", self.file], shell=True)
return doc
def Poll(self):
print "polling"
print self.doc.poll()
print self.doc.pid
def end(self):
try:
print "killing file {}".format(self.file)
except:
print "file has already been killed"
def main():
app = wx.PySimpleApp()
gui = GUI()
gui.Show()
app.MainLoop()
if __name__ == "__main__": main()
一些额外说明
- 我不关心便携性,它只能在办公室周围的几台受控计算机上运行
- 我认为这并不重要,但我正在通过批处理文件运行
pythonw可执行文件
更新
我玩了一点subprocess.Popen(),但遇到了同样的问题。我可以使用
Popen 对象
doc = subprocess.Popen(["start", "Full\\Path\\to\\File.txt"], shell=True)
但是当我poll() 对象时,它总是返回0。文档说A None value indicates that the process hasn’t terminated yet 所以0 意味着我的进程已经终止。因此,尝试kill() 它什么也不做。
我怀疑这是因为当start 命令完成并启动文件时该过程完成。我想要一些即使在文件启动后也能继续运行的东西,这可以用Popen() 完成吗?
【问题讨论】:
-
我认为每个文件的默认程序的概念并不容易移植。如果你在 Freedesktop.org 系统上,
xdg-open是票,在 OSX 上它只是简单的open,而在 Windows 上,我相信你通常会使用start(并让它以新的和有趣的方式失败出于非显而易见的原因,如果以前的表现是任何指标)。 -
@tripleee 我不太关心可移植性,因为这是用于受控办公室计算机上的脚本。
-
@wnnmaw 这个
startfile功能与触发子进程完全不同。它创建了一个独立进程,即使你有 PID,它也不会对你有任何好处,因为没有 root 权限你将无法杀死它。 -
@freakish 我不想使用
startfile的另一个原因@
标签: python windows shell subprocess popen