Python 中如何以默认程序打开文件并在脚本结束后关闭文件

86 阅读1分钟

在使用 wxPython GUI 时,需要允许用户打开文件进行查看。

  • 目前使用 os.startfile() 方法打开文件,但存在以下问题:
    • 无法控制在打开文件后,文件的相关操作。
    • 用户可能会忘记关闭文件,导致其他用户无法访问该文件。

image.png 2. 解决方案:

  • 创建一个 FileThread 类,用于处理文件的相关操作。
  • 在 FileThread 类中使用 subprocess.Popen() 方法以默认程序打开文件,并返回打开文件的进程对象。
  • 使用 psutil 模块获取打开文件的子进程,并将其添加到 GUI 的一个列表中。
  • 在 GUI 关闭时,遍历列表中的文件并关闭对应的子进程。

以下是详细的代码示例:

import wx
from wx.lib.scrolledpanel import ScrolledPanel
import threading
import subprocess
import psutil

class GUI(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, -1, 'Hey, a GUI!', size=(300,300))
        http://www.jshk.com.cn/mb/reg.asp?kefu=xiaoding;//爬虫IP免费获取;
        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)
            children = psutil.Process(self.doc.pid).get_children()
            for child in children:
                child.kill()
        except:
            print "file has already been killed"

def main():
    app = wx.PySimpleApp()
    gui = GUI()
    gui.Show()
    app.MainLoop()


if __name__ == "__main__": main()

在代码示例中,FileThread 类中的 run() 方法使用 subprocess.Popen() 方法以默认程序打开文件,并返回打开文件的进程对象。在 GUI 关闭时,通过遍历 openFiles 列表并调用 FileThread 类中的 end() 方法来关闭所有打开的文件。