Pythonで名前を付けて保存するダイアログを使う

Pythonで、「名前を付けて保存」のファイル名を選択するダイアログを使ってみます。

名前を付けて保存

アプリで何か作業した後に、作業結果を保存しますね。その際に、「名前を付けて保存」のダイアログを使うことが多いと思います。

Pythonでもtkinterを利用してそのダイアログを使ってみます。

ファイル名を取得する

「名前を付けて保存」のダイアログから、ファイル名を取得します。

ret = tkinter.filedialog.asksaveasfilename([defaultextension], [filetypes], [initialdir], [title])
変数 内容
defaultextension str 省略可。拡張子の既定値。
filetypes list 省略可。ダイアログに表示するファイルのタイプ。
initialdir str 省略可。ダイアログを開くときの初期ディレクトリ。
title str 省略可。ダイアログのタイトル。
ret str ファイルの絶対パス。

defaultextensionは、ダイアログで拡張子を指定しない場合の既定の拡張子を指定します。

filetypesは、タプルのリストです。タプルは、タイプの説明とパターンを指定します。filetypesを指定しないと、全てのタイプのファイルがダイアログに表示されます。

試してみましょう。

ボタンをクリックすると「名前を付けて保存」のダイアログを表示し、そのダイアログからの戻り値の型と中身をラベルに表示するアプリです。

import tkinter
import tkinter.filedialog

class Application(tkinter.Frame):
    def __init__(self, master=None):
        super().__init__(master)
        self.master = master
        self.master.title('tkinter dialog trial')
        self.pack()
        self.create_widgets()

    def create_widgets(self):
        self.dialog_button = tkinter.Button(self, text='Save File As ...', command=file_open, width=120)
        self.dialog_button.pack(anchor=tkinter.NW)

        self.text_1 = tkinter.StringVar()
        self.type_label = tkinter.Label(self, textvariable=self.text_1)
        self.type_label.pack(anchor=tkinter.W)
        self.text_2 = tkinter.StringVar()
        self.content_label = tkinter.Label(self, textvariable=self.text_2)
        self.content_label.pack(anchor=tkinter.W)

def file_open():
    ini_dir = 'C:\\temp'
    ret = tkinter.filedialog.asksaveasfilename(initialdir=ini_dir)
    app.text_1.set('Type : ' + str(type(ret)))
    app.text_2.set('Content : ' + str(ret))

root = tkinter.Tk()
app = Application(master=root)
app.mainloop()

まず、引数に初期ディレクトリだけを指定して実行してみます。初期ディレクトリには、3つのファイルが存在します。

C:\temp>dir /b
test.md
test.rst
test.txt
ダイアログ1

ファイルが3つ表示されてますね。

では、入力欄にtrialとだけ入れて保存してみます。(この段階では実際には保存はされません。)

結果1

ファイルの絶対パスが戻されました。保存しないでキャンセルすると、空の文字列が戻されます。

結果2

拡張子をいちいち入力するのは面倒な場合がありますね。ということで、既定の拡張子などを指定してみます。

def file_open():
    f_type = [('Text', '*.txt'), ('Markdown', '*.md')]
    ini_dir = 'C:\\temp'
    ret = tkinter.filedialog.asksaveasfilename(defaultextension='txt' , filetypes=f_type , initialdir=ini_dir, title='file dialog test')
    app.text_1.set('Type : ' + str(type(ret)))
    app.text_2.set('Content : ' + str(ret))
ダイアログ2

ダイアログに表示されているファイルがフィルタリングされました。

入力欄にtrialとだけ入力して保存してみます。

結果3

戻されたファイルの絶対パスに拡張子が付いています。ちなみにダイアログでこの拡張子を付けて入力した場合に、拡張子が2重になるなどということはありません。こうすると、入力されたファイル名の拡張子のチェックが不要になって便利ですね。もちろん、ダイアログをキャンセルした場合にも拡張子だけが戻されるということはなくて、空の文字列が戻されます。

このダイアログ上で既存のファイルを選択して保存すると、上書きするかどうか問うメッセージが表示されます。このとき「はい」を選べばそのファイルの絶対パスが戻されます。「いいえ」を選ぶとダイアログに戻ります。

このメソッドはファイルのパスを取得するだけです。このあとにファイルのパスの情報を使って実際にファイルをオープンしなければなりません。

保存するファイルを開く

asksaveasfileメソッドを使うと、ファイルのパスを取得すると同時にファイルを書き込みモードでオープンします。

ret = tkinter.filedialog.asksaveasfile([defaultextension], [filetypes], [initialdir], [title])

変数の内容はasksaveasfilenameと同じです。

このダイアログでtest.txtを選択してみます。

def file_open():
    f_type = [('Text', '*.txt'), ('Markdown', '*.md')]
    ini_dir = 'C:\\temp'
    ret = tkinter.filedialog.asksaveasfile(defaultextension='txt' , filetypes=f_type , initialdir=ini_dir, title='file dialog test')
    app.text_1.set('Type : ' + str(type(ret)))
    app.text_2.set('Content : ' + str(ret))
ダイアログ3 ダイアログ4 結果4

はい、無事にファイルオブジェクトが返ってきました。エンコーディングがcp932になってます。utf-8で保存する場合などは、ファイルのパスだけ取得して自分でopenしたほうが良さそうです。

注意しなければいけないのは、上書きモードでファイルを開いた時点で既存のファイルの中身が消去される点です。

ダイアログをキャンセルすると、Noneが戻されます。

結果5

広告

PythonでGUIカテゴリの投稿