【问题标题】:Quick and easy file dialog in Python?Python 中快速简单的文件对话框?
【发布时间】:2023-03-29 18:53:01
【问题描述】:

我有一个简单的脚本,它解析文件并将其内容加载到数据库中。我不需要 UI,但现在我提示用户使用最不友好的 raw_input 解析文件,尤其是因为用户无法复制/粘贴路径。我想要一种快速简便的方法向用户显示文件选择对话框,他们可以选择文件,然后将其加载到数据库中。 (在我的用例中,如果他们碰巧选择了错误的文件,它会解析失败,即使加载到数据库也不会有问题。)

import tkFileDialog
file_path_string = tkFileDialog.askopenfilename()

这段代码接近我想要的,但它留下了一个恼人的空框架打开(无法关闭,可能是因为我没有注册关闭事件处理程序)。

我不必使用 tkInter,但由于它在 Python 标准库中,因此它是最快和最简单的解决方案的理想选择。

在没有任何其他 UI 的情况下,在脚本中提示文件或文件名的快速简便方法是什么?

【问题讨论】:

    标签: python openfiledialog


    【解决方案1】:

    如果您不想拥有任何其他依赖项,Tkinter 是最简单的方法。 要仅显示对话框而不显示任何其他 GUI 元素,您必须使用 withdraw 方法隐藏根窗口:

    import tkinter as tk
    from tkinter import filedialog
    
    root = tk.Tk()
    root.withdraw()
    
    file_path = filedialog.askopenfilename()
    

    Python 2 变体:

    import Tkinter, tkFileDialog
    
    root = Tkinter.Tk()
    root.withdraw()
    
    file_path = tkFileDialog.askopenfilename()
    

    【讨论】:

    • 这应该是公认的答案。它简单、有效,只要您不一遍又一遍地创建新的 Tk 根窗口就可以了(更不用说这正是我遇到此线程时正在寻找的答案)。
    • 我也将它用于我的工作。它在 Fedora 上运行良好,但在 Ubuntu 上它会弄乱后面的任何 matplotlib 数据。几乎在 pylab.show() 之后它挂起。我仍然可以在终端中输入,但没有任何反应。对于我的程序,cpu 也变为 0%。有什么建议吗?
    • 在 python3 上:tkinter.filedialog.askopenfilename()
    • 在 python2 上:import Tkinter as tkimport tkFileDialogfile_path = tkFileDialog.askopenfilename()
    • 这在 MacOS 上效果不佳:对话框打开但变得无响应并且整个脚本挂起。
    【解决方案2】:

    你可以使用easygui:

    import easygui
    
    path = easygui.fileopenbox()
    

    要安装easygui,可以使用pip

    pip3 install easygui
    

    它是一个使用 tkinter 的纯 Python 模块 (easygui.py)。

    【讨论】:

    • easygui 项目已关闭,未进一步维护——它目前在 Python 3.5 上运行时会引发错误/异常,或许可以考虑其他选项
    • @pepe:我在the project repository 中没有看到任何通知(最新提交是 5 月 15 日)
    • 很高兴知道,谢谢,也许有人捡到了:见easygui.wordpress.com/2013/03/06/easygui-project-shuts-down-2
    • @Zanam 显然它确实有效。但可能有bugs
    • 如果你们在使用 tkinter + matplotlib 组合时遇到问题,它可以为您节省一天的时间!
    【解决方案3】:

    试试wxPython:

    import wx
    
    def get_path(wildcard):
        app = wx.App(None)
        style = wx.FD_OPEN | wx.FD_FILE_MUST_EXIST
        dialog = wx.FileDialog(None, 'Open', wildcard=wildcard, style=style)
        if dialog.ShowModal() == wx.ID_OK:
            path = dialog.GetPath()
        else:
            path = None
        dialog.Destroy()
        return path
    
    print get_path('*.txt')
    

    【讨论】:

      【解决方案4】:

      如果您不需要 UI 或希望程序在 CLI 中运行,您可以将文件路径解析为参数。这将允许您使用 CLI 的自动完成功能快速找到您需要的文件。

      这可能只有在脚本除了文件路径输入之外是非交互式的时才会方便。

      【讨论】:

      • 这是一个有效的解决方案,虽然每次我不得不使用 Windows 命令行时我都会感到难过。我在 Windows 环境中。
      • 我明白了。与 Unix 相比,Windows 中的 CLI 非常糟糕。我明白为什么文件选择器会很整洁。我想也许将文件拖放到脚本上,然后读取文件名作为参数? (mindlesstechnology.wordpress.com/2008/03/29/…) 如果不涉及首先物理复制文件,那将变得容易得多。我不在 Windows 盒子 ATM 上,所以我无法测试它的行为。如果您需要在多台机器上安装注册表黑客,您可以轻松地将其部署在 .reg 文件中。
      • 或者,您可以让 .bat 文件将文件名作为参数传递给脚本。这不涉及任何注册表黑客。
      【解决方案5】:

      pywin32 提供对GetOpenFileName win32 函数的访问。来自example

      import win32gui, win32con, os
      
      filter='Python Scripts\0*.py;*.pyw;*.pys\0Text files\0*.txt\0'
      customfilter='Other file types\0*.*\0'
      fname, customfilter, flags=win32gui.GetOpenFileNameW(
          InitialDir=os.environ['temp'],
          Flags=win32con.OFN_ALLOWMULTISELECT|win32con.OFN_EXPLORER,
          File='somefilename', DefExt='py',
          Title='GetOpenFileNameW',
          Filter=filter,
          CustomFilter=customfilter,
          FilterIndex=0)
      
      print 'open file names:', repr(fname)
      print 'filter used:', repr(customfilter)
      print 'Flags:', flags
      for k,v in win32con.__dict__.items():
          if k.startswith('OFN_') and flags & v:
              print '\t'+k
      

      【讨论】:

      • 这将我当前的工作目录更改为从中选择文件的目录。遇到这种情况该怎么办?
      • @Mooncrater 将|win32con.OFN_NOCHANGEDIR 添加到Flags,但要注意警告stackoverflow.com/questions/50468051/…
      • 您好,谢谢您的建议。我最终做的是恢复到原始目录,每次我使用GetOpenFileNameW
      【解决方案6】:

      使用 tkinter (python 2) 或 Tkinter (python 3) 确实可以显示文件打开对话框(请参阅此处的其他答案)。但请注意,该对话框的用户界面已过时,与 Windows 10 中可用的较新文件打开对话框不对应。

      此外 - 如果您正在寻找将 python 支持嵌入到您自己的应用程序中的方法 - 您很快就会发现 tkinter 库不是开源代码,甚至更多 - 它是商业库。

      (例如搜索“activetcl 定价”将带您进入此网页:https://reviews.financesonline.com/p/activetcl/

      因此,任何想要嵌入 python 的应用程序都需要花钱购买 tkinter 库。

      我自己设法找到了pythonnet库:

      (麻省理工学院许可证)

      使用以下命令可以安装pythonnet:

      pip3 install pythonnet
      

      您可以在这里找到使用打开文件对话框的工作示例:

      https://stackoverflow.com/a/50446803/2338477

      让我在这里也复制一个例子:

      import sys
      import ctypes
      co_initialize = ctypes.windll.ole32.CoInitialize
      #   Force STA mode
      co_initialize(None)
      
      import clr 
      
      clr.AddReference('System.Windows.Forms')
      
      from System.Windows.Forms import OpenFileDialog
      
      file_dialog = OpenFileDialog()
      ret = file_dialog.ShowDialog()
      if ret != 1:
          print("Cancelled")
          sys.exit()
      
      print(file_dialog.FileName)
      

      如果您还错过了更复杂的用户界面 - 请参阅 Demo 文件夹 在pythonnet git中。

      我不确定是否可以移植到其他操作系统,还没有尝试过,但是 .net 5 计划移植到多个操作系统(搜索“.net 5 平台”,https://devblogs.microsoft.com/dotnet/introducing-net-5/) - 所以这项技术也是未来的证明。

      【讨论】:

      • 此解决方案仅适用于 Windows。在 linux .NET 上安装。 o 只使用 python 中的 FileOpen 对话框?可笑...
      • 还没试过。 python .net 需要移植到 .net 核心,之后还需要打开文件对话框。不确定什么时候会发生。需要尝试当前的技术提供什么。
      【解决方案7】:

      另一个与操作系统无关的选项,使用pywebview

      import webview
      
      def webview_file_dialog():
          file = None
          def open_file_dialog(w):
              nonlocal file
              try:
                  file = w.create_file_dialog(webview.OPEN_DIALOG)[0]
              except TypeError:
                  pass  # user exited file dialog without picking
              finally:
                  w.destroy()
          window = webview.create_window("", hidden=True)
          webview.start(open_file_dialog, window)
          # file will either be a string or None
          return file
      
      print(webview_file_dialog())
      
      

      环境:Mac 上的 python3.8.6 - 虽然我之前在 windows 10 上使用过 pywebview。

      【讨论】:

        猜你喜欢
        • 2011-04-04
        • 2011-09-17
        • 1970-01-01
        • 2013-09-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多