Hộp thoại tệp nhanh chóng và dễ dàng bằng Python?


104

Tôi có một tập lệnh đơn giản để phân tích cú pháp một tệp và tải nội dung của nó vào cơ sở dữ liệu. Tôi không cần giao diện người dùng, nhưng ngay bây giờ tôi đang nhắc người dùng phân tích cú pháp tệp bằng cách sử dụng raw_inputkhông thân thiện nhất, đặc biệt là vì người dùng không thể sao chép / dán đường dẫn. Tôi muốn một cách nhanh chóng và dễ dàng để trình bày hộp thoại chọn tệp cho người dùng, họ có thể chọn tệp và sau đó nó được tải vào cơ sở dữ liệu. (Trong trường hợp sử dụng của tôi, nếu họ tình cờ chọn sai tệp, nó sẽ không phân tích được và sẽ không thành vấn đề ngay cả khi nó đã được tải vào cơ sở dữ liệu.)

import tkFileDialog
file_path_string = tkFileDialog.askopenfilename()

Mã này gần với những gì tôi muốn, nhưng nó để lại một khung trống khó chịu mở (không thể đóng, có thể do tôi chưa đăng ký trình xử lý sự kiện đóng).

Tôi không phải sử dụng tkInter, nhưng vì nó nằm trong thư viện chuẩn Python nên nó là một ứng cử viên sáng giá cho giải pháp nhanh nhất và dễ dàng nhất.

Có cách nào nhanh chóng và dễ dàng để nhắc tệp hoặc tên tệp trong tập lệnh mà không cần bất kỳ giao diện người dùng nào khác?


Chỉnh sửa nhỏ: Bạn có thể dán vào thiết bị đầu cuối (có vẻ như bạn đang sử dụng Windows) bằng cách nhấp chuột phải vào vùng văn bản và chọn "Dán" từ trình đơn ngữ cảnh.
Deestan

1
Không có menu chuột phải nào có sẵn trong lời nhắc Python raw_input.
Buttons840

2
raw_input xảy ra trong terminal có menu chuột phải.
Deestan

Câu trả lời:


200

Tkinter là cách dễ nhất nếu bạn không muốn có bất kỳ phụ thuộc nào khác. Để chỉ hiển thị hộp thoại mà không có bất kỳ phần tử GUI nào khác, bạn phải ẩn cửa sổ gốc bằng withdrawphương pháp:

import tkinter as tk
from tkinter import filedialog

root = tk.Tk()
root.withdraw()

file_path = filedialog.askopenfilename()

Biến thể Python 2:

import Tkinter, tkFileDialog

root = Tkinter.Tk()
root.withdraw()

file_path = tkFileDialog.askopenfilename()

3
Đây phải là câu trả lời được chấp nhận. Nó đơn giản, hiệu quả và miễn là bạn không tạo đi tạo lại nhiều lần các cửa sổ gốc Tk mới là ổn (và chưa kể đó chính xác là câu trả lời mà tôi đang tìm kiếm khi xem qua chủ đề này).
Andrew

2
Tôi chỉ sử dụng cái này cho công việc của tôi. Nó hoạt động tốt trên Fedora, nhưng trên Ubuntu, nó làm rối tung bất kỳ số liệu matplotlib nào theo sau. Khá nhiều sau khi pylab.show () nó bị treo. Tôi vẫn có thể nhập thiết bị đầu cuối, nhưng không có gì xảy ra. Ngoài ra cpu đi về 0% cho chương trình của tôi. Có lời khuyên nào không?
Diana

17
Trên python3:tkinter.filedialog.askopenfilename()
JFS

10
Trên python2: import Tkinter as tkimport tkFileDialogfile_path = tkFileDialog.askopenfilename()
SaschaH

8
Điều này không hoạt động tốt trên MacOS: hộp thoại mở ra nhưng không phản hồi và toàn bộ tập lệnh bị treo.
Bảo trì định kỳ

26

Bạn có thể sử dụng easygui :

import easygui

path = easygui.fileopenbox()

Để cài đặt easygui, bạn có thể sử dụng pip:

pip3 install easygui

Nó là một mô-đun Python đơn thuần ( easygui.py) sử dụng tkinter.


6
dự án easygui đã đóng cửa, không tiếp tục duy trì - nó hiện ném một lỗi / ngoại lệ khi chạy trên Python 3.5, có lẽ xem xét các lựa chọn khác
pepe

2
@pepe: Tôi không thấy bất kỳ thông báo nào trong kho lưu trữ dự án (cam kết mới nhất là ngày 15 tháng 5)
jfs

thật tốt khi biết, thx, có lẽ ai đó đã nhặt nó lên: xem easygui.wordpress.com/2013/03/06/easygui-project-shuts-down-2
pepe

@Zanam rõ ràng là nó hoạt động. Nhưng có thể có lỗi .
jfs

Nếu các bạn gặp khó khăn với combo tkinter + matplotlib, nó có thể giúp bạn tiết kiệm một ngày!
Cuong Truong Huy,

20

Hãy thử với 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')

5

Nếu bạn không cần giao diện người dùng hoặc muốn chương trình chạy trong CLI, bạn có thể phân tích cú pháp đường dẫn tệp như một đối số. Điều này sẽ cho phép bạn sử dụng tính năng tự động hoàn thành của CLI để nhanh chóng tìm thấy tệp bạn cần.

Điều này có lẽ sẽ chỉ hữu ích nếu tập lệnh không tương tác ngoài đầu vào đường dẫn tệp.


Đây là một giải pháp hợp lệ, mặc dù tôi cảm thấy buồn trong lòng mỗi khi phải sử dụng dòng lệnh Windows. Tôi đang ở trong môi trường Windows.
Buttons840, 16/02/12

2
Tôi hiểu rồi. CLI trong Windows quá tệ so với Unix. Tôi hiểu tại sao một bộ chọn tệp sẽ gọn gàng. Tôi đoán có thể kéo và thả tệp vào tập lệnh và sau đó đọc tên tệp dưới dạng đối số? ( mindlesstechnology.wordpress.com/2008/03/29/… ) Điều đó sẽ làm cho nó dễ dàng hơn rất nhiều nếu nó không liên quan đến việc sao chép vật lý tệp trước. Tôi không sử dụng máy ATM hộp Windows nên không thể kiểm tra hoạt động của nó. Bạn có thể dễ dàng triển khai hack registry trong tệp .reg nếu bạn cần cài đặt nó trên một số máy.
SQDK

Ngoài ra, bạn có thể có một tệp .bat chuyển tên tệp vào tập lệnh làm đối số. Điều này không liên quan đến bất kỳ vụ hack đăng ký nào.
SQDK

2

Kiểm tra EasyGUI, một mô-đun rất dễ sử dụng sẽ thực hiện công việc - http://easygui.sourceforge.net/

Bạn sẽ sử dụng hàm fileopenbox được nêu chi tiết trên trang tài liệu api này - https://easygui.readthedocs.io/en/latest/api.html


1
Xin lỗi - trên điện thoại của tôi nên tôi không thể đưa ra ví dụ. Bạn muốn sử dụng fileopenbox - ferg.org/easygui/easygui.html#-fileopenbox
timc 16/02/12

Liên kết thứ hai bị hỏng.
Thomas Andrews

1

pywin32cung cấp quyền truy cập vào GetOpenFileNamechức năng win32. Từ ví dụ

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

1

Sử dụng tkinter (python 2) hoặc Tkinter (python 3), thực sự có thể hiển thị hộp thoại mở tệp (Xem các câu trả lời khác tại đây). Tuy nhiên, xin lưu ý rằng giao diện người dùng của hộp thoại đó đã lỗi thời và không tương ứng với các hộp thoại mở tệp mới hơn có sẵn trong Windows 10.

Hơn nữa - nếu bạn đang tìm cách nhúng hỗ trợ python vào ứng dụng của riêng mình - bạn sẽ sớm phát hiện ra rằng thư viện tkinter không phải là mã nguồn mở và thậm chí hơn thế nữa - nó là thư viện thương mại.

(Ví dụ: tìm kiếm "giá activetcl" sẽ dẫn bạn đến trang web này: https://reviews.financesonline.com/p/activetcl/ )

Vì vậy, thư viện tkinter sẽ tốn tiền cho bất kỳ ứng dụng nào muốn nhúng python.

Tôi đã tự mình quản lý để tìm thư viện pythonnet:

(Giấy phép MIT)

Sử dụng lệnh sau, bạn có thể cài đặt pythonnet:

pip3 install pythonnet

Và ở đây bạn có thể tìm hiểu ví dụ làm việc để sử dụng hộp thoại tệp mở:

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

Hãy để tôi sao chép một ví dụ cũng ở đây:

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)

Nếu bạn cũng bỏ lỡ giao diện người dùng phức tạp hơn - hãy xem thư mục Demo trong pythonnet git.

Tôi không chắc về khả năng chuyển sang hệ điều hành khác, chưa thử, nhưng .net 5 được lên kế hoạch để chuyển sang nhiều hệ điều hành (Tìm kiếm "nền tảng .net 5", https://devblogs.microsoft.com/dotnet/introductioning -net-5 / ) - vì vậy công nghệ này cũng là bằng chứng trong tương lai.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.