素人がプログラミングを頑張る

初心者によるPythonを中心としたプログラミングの学習過程を記録

DjangoでWebアプリ作成(CSSの本番環境への適用)

前回はローカルサーバーを用いてCSSが適用されたかを確認しましたが、次は本番環境に適用させてみたいと思います。静的ファイルをサーバーへアップすればOK!というわけではなく、本番環境への適用には追加で別の設定が必要になります。このあたりがWeb関係のややこしいところですが、少しずつ理解していきたいと思います。

※Herokuへのデプロイができることを前提に話を進めます。Herokuへのデプロイ方法は、Configuring Django Apps for Heroku | Heroku Dev Centerを参考に設定しました。

静的ファイルの本番環境への適用方法

まずはDjango公式サイトの、静的ファイルのデプロイ方法を紹介しているページ静的ファイルのデプロイ | Django documentation | Djangoを確認してみましたが、、、初心者には厳しい内容で早々にあきらめました。

いろいろ検索していると、Herokuのサイト中Django and Static Assets | Heroku Dev Centerに非常にわかりやすい説明を見つけましたが、英語で書かれているのと、一部仕様が変わっているようなので以下にまとめなおしました。

1. WhiteNoiseのインストール

pipenv install whitenoiseを実行し、WhiteNoiseをインストールします。WhiteNoiseは、WhiteNoise — WhiteNoise 4.1.2 documentationにRadically simplified static file serving for Python web appsと書かれている通り、Python Webアプリ用に静的ファイルの設定をしてくれるソフトの様です。詳細は残念ながら理解できませんでしたが、とりあえず今は細かいところは置いておきましょう。

2. settings.pyの編集

次に、settings.pyを修正していきます。 まずは最下部を、以下の様に修正します。最後の2行を追加しています。(ここも、具体的に何をしているかは理解できませんでした。)

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.1/howto/static-files/

STATIC_URL = '/static/'
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')]

STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles') #追加
STATICFILES_STRAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage' #追加

さらに、settings.pyの真ん中あたりにあるMIDDLEWAREに、WhiteNoiseを追加します。Herokuの説明ページでは、MIDDLEWARE_CLASSES内にWhiteNoiseを追加していますが、現在のバージョンでは廃止されているようなので注意してください。

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'whitenoise.middleware.WhiteNoiseMiddleware', #追加
]

以上で準備は完了です。簡単ですね!早速Herokuへデプロイし、アクセスしてみます。

https://potato-projects.herokuapp.com/

※Herokuの無料版なので、ページが表示されるまでちょっと時間がかかります。

f:id:vigilantPotato:20181217210826j:plain
本番環境

無事、本番環境へもCSSを適用することができました。ローカルサーバーではなく、だれでもアクセスできるサーバーに公開できるとかなりうれしいですね。中身がスカスカなので、今後頑張っていきます。

DjangoでWebアプリ作成(CSSの適用方法)

Djangoを用いたWebアプリ作成の続きです。

今回は、サイトの見た目をある程度整えておいたほうがモチベーションが上がると思い、DjangoCSSファイルを適用する方法について調べました。

静的ファイル(画像、CSSJavascript)の適用方法

Djangoでは、画像、CSSJavascriptファイルは静的ファイル(static file)と呼んでいて、公式サイトにその適用手順がまとめられています。ただ、公式サイトは少し説明が不親切で、私のような完全な初心者にはわかりづらかったため、公式サイトの手順(静的ファイル (画像、JavaScript、CSS など) を管理する | Django documentation | Django)を引用しながら詳しい手順をまとめていきたいと思います。

1. 設定ファイルの確認

django.contrib.staticfiles が設定ファイルの INSTALLED_APPS に含まれていることを確認する。

プロジェクトフォルダにあるsettings.pyを開き、INSTALLED_APPをの中にdjango.contrib.staticfilesが存在していることを確認します。基本的にインストール時点で記述されているので、自分で消していなければあるはずです。

# Application definition
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

2. STATIC_URLの設定

設定ファイルの中で、STATIC_URL を設定します。

settings.pyを一番下まで見ていくと、以下の様なコードがあります。STATIC_URLに、作成する静的ファイルの保管用フォルダ名を記載していくと、Djangoがそのフォルダを見に行ってくれるようになります。公式では/static/としており、特にこだわりがなければそのままがわかりやすいでしょう。

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.1/howto/static-files/

STATIC_URL = '/static/'

3. htmlファイルの設定

テンプレート中では、static テンプレートタグを使うことで、設定済みの STATICFILES_STORAGE を含むある相対パスの URL を生成することができます。

{% load static %}
<img src="{% static "my_app/example.jpg" %}" alt="My image">

このあたりの日本語が怪しく、内容も分かりづらくて少し苦労しました。要するに、静的ファイルを呼び出す前に{% load static %}を記載し、実際に呼び出すときにはファイル名を"{% static Filename %}"とすればOKの様です。上記の例では、my_app/static/my_appフォルダ内のexample.jpgファイルを表示してくれます。

4. 静的ファイルの保存

アプリケーション内に static というフォルダを作って静的ファイルを保存してください。例えば、my_app/static/my_app/example.jpg となります。

最後に、アプリケーションフォルダ内にstaticフォルダを作成し、その中に静的ファイルを保管して完了です。上記の例では、staticフォルダ内にmy_appフォルダを作成してその中にexample.jpgファイルを保管しておけばOKですね。

静的ファイル保管フォルダの設定方法

上記の方法ではアプリごとに静的ファイルを持つことになるため、各アプリ共通の静的ファイルを使用する場合はとても不便ですが、そのような場合のための対応方法が、公式サイトの同じページ(静的ファイル (画像、JavaScript、CSS など) を管理する | Django documentation | Django)で紹介されています。以下の通りです。

プロジェクトには、特定のアプリケーションに紐付けられていない 静的な assets があることがあります。その場合には、アプリケーション内の static/ ディレクトリの他に、設定ファイルでディレクトリのリスト (STATICFILES_DIRS) を定義して、Django が静的ファイルを検索できるようにすることができます。たとえば、次のように設定します。

STATICFILES_DIRS = [
    os.path.join(BASE_DIR, "static"),
    '/var/www/static/',
]

これで理解できる初学者がどれほどいるのでしょうか。このあたりで、英語版で確認したほうが良いことを確信しました(英語の勉強にもなるし…)。ここの説明の意味するところは、STATICFILES_DIRで静的ファイルを保管するフォルダを別に設定してあげれば、Djangoはそのフォルダにも探しに行ってくれるよ!ということの様です。BASE_DIRはプロジェクトやアプリのフォルダが保存されているフォルダで、プロジェクトの最上位フォルダになります。上記の例では、最上位フォルダ内のstaticフォルダを静的ファイル保管用として設定しています。各アプリ内に保管するよりもわかりやすそうなので、私はこちらの方法で静的フォルダを管理することにしました。

以下の様に、STATICFILES_DIRSの設定をsetting.pyに追加し、最上位フォルダにstaticフォルダを作成して準備はOKです。

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.1/howto/static-files/

STATIC_URL = '/static/'
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')] #追加

f:id:vigilantPotato:20181216195302j:plain
staticフォルダ

staticフォルダ内に静的ファイルを保管し、htmlファイルから呼び出して使えるようになったので、試しに適当に拾ってきたCSSを適用させてサイトを表示させてみました。

f:id:vigilantPotato:20181216201106j:plain
CSS適用

CSSを使えると、かなりサイトっぽくなりますね。見た目がはっきりと変わってくれるとモチベーションが上がります。形から入るのも重要ですね。設定はかなりめんどうですが、今回の件でDjangoがどのように設定ファイルを検索しているのか少し理解できたと思います。

引き続き、少しずつ学んでいきます。

Pythonで簡単なデスクトップアプリ作成(WordClipper その8)

プログラミング言語を覚えるには実践が一番効果的と思い、デスクトップアプリWordClipperを作成してきました。いろいろと苦労はありましたが、自分自身が便利と思えるアプリを一から調べながら作成していくのは非常に楽しく、モチベーションを高く保つことができたと思います。一通り基礎的な機能が実装でき、実際に使用して非常に便利なため、一度機能や使い方をまとめます。今後もこのアプリを改良しながら、他のアプリにもチャレンジしていきたいと思います。

WordClipperアプリの機能

  1. ボタンクリックで登録した文字列をクリップボードにコピーする
  2. アプリ上で文字列の登録、削除ができる
  3. クリップボードにコピーと同時に登録したアドレスをブラウザで開く
  4. アプリ上でボタンの配置入れ替えができる
  5. 起動時、アプリをデスクトップ右端に表示する

最初は1と2の機能だけを実装しようと思っていたのですが、コードを書きながらこれもできるのでは?と思い、3、4、5を追加しました。

アプリの使用例

  1. パスワードの入力が必要になるサイトを複数利用する場合に特に便利!パスワードとサイトのアドレスを登録しておけば、ボタンクリックでブラウザが起動してサイトを開き、Ctrl+Cでパスワードを入力できるようになります。
  2. コピーする文字列の登録を省略してアドレスだけ登録すれば、単なるwebサイトへのショートカットとしても利用できます。
  3. webサイトだけでなく、フォルダやファイルのパスを登録してボタンクリックで開くこともできます。
  4. パスの登録を省略すれば、登録した文字列をクリップボードへのコピーする機能のみを利用できます。

webサイト、フォルダ、ファイルへのショートカットをデスクトップの右端に整理して表示させることができるため、デスクトップが非常にすっきりします。

使い方

1. 起動

ソースコードは以下にありますので、仮想環境を構築してスクリプト実行してください。または、zipファイル内にpyinstallerでexe化したファイルがありますので、そちらを実行しても起動できます。(ウィルスソフトが警告を出してきますが、無視して起動して大丈夫です。)

今回は、exeファイルを用いてアプリを起動してみます。まず、exeファイルを適当なフォルダ内に保存しておきます。

フォルダ

exeファイルを実行すると、以下の画面がデスクトップ右上に表示されます。ボタンを生成するためのword_list.csvが同じフォルダに存在しないため、クリップボタンはありません。

起動時

2. ボタンの登録

ボタンの登録には、create newボタンをクリックします。以下の様な入力用のダイアログが出現し、タイトル、コピーする文字列、パスの順番で入力を求められるので、それぞれ入力してください。今回は、タイトル:Google、コピーする文字列:Google!Google!Google!、パス:https://www.google.comとしました。

入力用ダイアログ

入力が完了すると、フォルダにword_list.csvファイルが作成されます。

フォルダ2

また、アプリが更新されてGoogleボタンが表示されます。

ボタン追加時

生成されたGoogleボタンを押すと、登録した文字列がクリップボードにコピーされ、同時にパスをブラウザで開きます。Ctrl+Cで登録した文字列をペーストできます。

f:id:vigilantPotato:20181215213257j:plain
クリップボタンクリック時

Webサイトだけでなく、フォルダやファイルを直接開くこともできるので、ショートカットとして利用できます。また、パスを入力しないで利用することもできます。

3. ボタンの削除

delete buttonにチェックを入れた状態でクリップボタンをクリックすると、そのボタンを削除することができます。

4. ボタンの入れ替え

swap buttonにチェックを入れた状態でクリップボタンを2つクリックすると、クリックした2つのボタンの位置を入れ替えることができます。

まとめ

基本的な機能はこれで揃いました。当初考えていた以上に簡単にアプリが作成できて非常に驚いています。しかもかなり便利で現在ではWordClipperを愛用しています。

Python アプリ画面のサイズ・位置設定(tkinter)

tkinterを用いてデスクトップアプリを作成し、実際に使用しているうちに、アプリの機能とは別のところにも不満が出てくるようになりました。それは、アプリ起動時に画面がスクリーン中央付近にできてしまうことです。今までは手動でスクリーンの右上に移動させていましたが、最初からその位置へ現れてくれるとひと手間がなくなり、ストレスがなくなりそうです。そこで、今回はtkinterのアプリ画面の初期位置を設定する方法を調べてまとめました。ついでに画面サイズの設定方法も。

以下の2つの内容を、実際にコードを書きながらまとめていきます。

  1. 画面サイズの設定方法
  2. 位置の設定方法

1. 画面サイズの設定方法

まず、実際に画面を生成するコードを作成し、動きを確認していきたいと思います。以下のコードではアプリの画面をサイズを指定し、画面を表示させます。

コード

import tkinter

if __name__ == '__main__':
    root = tkinter.Tk()
    root.geometry('300x300')
    root.mainloop()

コードの解説

解説というほどのことはないですね。作成したTkオブジェクトに対して、geometryメソッドで画面サイズを渡してあげるだけです。とても簡単に画面サイズを設定することができます。画面サイズは縦x横をピクセルで表記し、文字列で渡します。画面の中身を何も設定していないので、実行すると空白の画面が指定のサイズで現れます。

2. 位置の設定方法

次に、画面の出現位置の設定方法についてです。コードに出現位置の設定を追加していきます。まず、以下に位置指定がないときの起動時の画面を示します。

f:id:vigilantPotato:20181214233345j:plain
位置指定なし

中途半端な位置にアプリ画面が出現していますね。この出現位置を操作し、スクリーンの左上に表示させてみたいと思います。

コード

import tkinter

if __name__ == '__main__':
    root = tkinter.Tk()
    root.geometry('300x300+0+0')
    root.mainloop()

コードの解説

位置指定なしの時と、ほとんど変わっていませんが、geometryメソッドに入力する値を、'300x300+0+0'に変更しています。こうすることで、300x300の画面をスクリーンの座標(0, 0)に表示することができます。以下が実行時の画面です。

f:id:vigilantPotato:20181214234230j:plain
位置指定有

スクリーンの座標は、左上が(0, 0)のため、アプリ画面はスクリーン左上部に表示されました。画面サイズの後に位置座標を追加するだけでアプリ画面の出現位置を調整することができました。

最後に右上に表示させる場合のコードを以下に示します。

コード

if __name__ == '__main__':
    root = tkinter.Tk()
    x = root.winfo_screenwidth() - 300
    y = 0
    root.geometry('300x300+%d+%d' % (x, y))
    root.mainloop()

コードの解説

まず、アプリの出現座標を変数(x, y)としました。xにはwinfo_screenwidthメソッドを用いて取得したスクリーンの横幅からアプリの横幅を引いた値を設定します。これによって、アプリはスクリーン右端に出現します。yは変わらず0です。xとyをgeometryメソッドに渡すときには、文字列置換を用いています。文字列置換の説明はここでは省きます。 では実際に起動してみましょう。

f:id:vigilantPotato:20181214235545j:plain
右上に位置指定

アプリ画面が右上に現れました。アプリの出現位置を簡単に調整することができ、目的に応じて設定するとアプリがより使いやすくなりそうです。

Pythonで簡単なデスクトップアプリ作成(WordClipper その7)

今回追加するのは、作成したクリップボタンの位置を自由に入れ替える機能です。これまでは、クリップボタンの順番を変更するには一度ボタンを削除して新たに作成しなおすか、csvファイルを直接操作するしかありませんでした。これでは非常に使い勝手が悪いので、改善していきたいと思います。

具体的には、チェックボタンにチェックを入れた状態でクリップボタンを二つクリックすると、それらの位置を入れ替えるようにしたいと思います。

コードの解説

コードが長いため、前回からの変更点のみを記載しています。最新版は以下を参照してください。

github.com

まず、create_widgetsメソッドに、チェックボタンを生成するコードを追記します。

def create_widgets(self):

     ~~~

    #swapチェックボタンを生成
    self.var_s = tkinter.BooleanVar()
    self.swap_check= tkinter.Checkbutton(self, text='swap button', var=self.var_s, command=self.swap_checked)
    self.swap_check.bind("<ButtonRelease-1>")
    self.widget_list.append(self.swap_check)
    self.swap_check.pack(anchor=tkinter.W, padx=5)

チェックボタンには、commandオプションでクリック時にswap_checkedメソッドを呼び出すように設定しています。

次はswap_checkedメソッドです。

def swap_checked(self):
    self.swap_list=[]
    if self.var_s.get() == True:
        self.delete_check.config(state='disable')
    else:
        self.delete_check.config(state='active')

このメソッドはチェックボックスにチェックが入った時かチェックを外したときに実行され、deleteチェックボックスを有効化または無効化します。また、入れ替えるボタンのオブジェクトを格納するリストを初期化します。

次はswap_buttonsメソッドです。実際に入れ替えを行う重要メソッドです。

def swap_buttons(self, text):
    if text == 'create new':
        return
    
    self.swap_list.append(text)
    if len(self.swap_list) == 2:
        for i, word in enumerate(self.word_list):
            if word[0] == self.swap_list[0]:
                swap1 = i
            if word[0] == self.swap_list[1]:
                swap2 = i
        self.word_list[swap1], self.word_list[swap2] =self.word_list[swap2], self.word_list[swap1]
        self.delete_check.config(state='active')
        self.renew_CSV()
        self.destroy_widgets()
        self.create_widgets()

チェックボタンにチェックを入れた状態でクリップボタンをクリックすると実行され、クリックしたボタンのタイトルをswap_listに追記していきます。swap_listlenが2になった時、つまり2つのボタンをクリックしたときに、入れ替えの処理が実行されます。if len(self.swap list) == 2以下では、クリックしたボタンのタイトルをword_listから検索し、そのインデックスを取得してリストの要素を入れ替えています。その後、csvファイルの更新、現在のウィジェットの破棄、ウィジェットの作成を実行しています。

最後に、word_clipメソッド内で、チェックボタンがクリックされているときにswap_buttonsを実行するコードを追加して完了です。

def word_clip(self, event):

    ~~~

    #swapチェックボタンにチェックが入っている場合
    if self.var_s.get() == True:
        self.swap_buttons(event.widget["text"])
        return

動作確認

早速起動して動作確認をしましょう。

起動時
起動時

swap_buttonが追加されました!チェックを入れてみます。

チェック時
チェック時

チェックを入れると、delete_buttonが無効化されました。swap_checkedメソッドがうまく動いてくれているようです。チェックを入れた状態で、GoogleとYahooボタンをクリックしてみます。

入れ替え
入れ替え

GoogleボタンとYahooボタンが入れ替わりました。swap_buttonsメソッドも問題なさそうですね!

まとめ

ボタンを入れ替える機能の追加が無事完了しました。最初はそれほど難しくない機能だろうと思っていたのですが、なかなか手ごわく少し時間がかかってしまいました。 ボタンの追加、削除、入れ替えと、基本的な機能がそろってアプリアプリしてきました。デザインが味気ないのでもう少し何とかならないかなと思っています。今後の課題とします。

Python ウィジェットの無効化(tkinter)

デスクトップアプリを作成中、チェックボタンを用いてウィジェットの有効・無効を切り替えたいと思い、方法を調べてみました。結果、configメソッドでstate='disable'とするだけで良さそうなので、簡単なコードを作成して動作を確認してみました。最初は記事にするほどの内容でもないと思っていたのですが意外とはまってしまい、解決まで苦労したので記録に残しておきたいと思います。

結論から述べると、.bindを用いると無効化できないです。

以下、私が実際に作成したコードを示しながら説明します。動作確認用には、チェックボタンにチェックを入れるとボタンウィジェットが無効になるコードを作成しました。上記の結論通り、以下のコードではボタンを無効化できません。

コード

import tkinter

class DisableButtonTest(tkinter.Frame):
    def __init__(self, master=None):
        super().__init__(master)
        
        #チェックボタンウィジェット
        self.var = tkinter.BooleanVar()
        check = tkinter.Checkbutton(self, text='disable button!', variable=self.var)
        check.bind("<ButtonRelease-1>", self.change_state)
        check.pack()

        #チェックボタンの状態を表示するボタンウィジェット
        self.button1 = tkinter.Button(master=self, text='True or False', width=20)
        self.button1.bind("<ButtonRelease-1>", self.show_status)
        self.button1.pack()

    def change_state(self, event):
        if self.var.get():
            self.button1["text"] = 'uncheck'
            self.button1.config(state='active')
        else:
            self.button1["text"] = 'check!'
            self.button1.config(state='disable')

    def show_status(self, event):
        self.button1["text"] = 'button is active!'

if __name__ == '__main__':
    root = tkinter.Tk()
    f = DisableButtonTest(master=root)
    f.pack()
    root.mainloop()

コードの解説

8~16行目でチェックボタンウィジェットとボタンウィジェットを作成し、.bindを用いてクリック時にそれぞれchange_stateshow_statusメソッドを実行するようにしています。18~24行目のchange_stateメソッドはチェックボタンクリック時に呼び出され、チェックボタンにチェックを入れると、ボタンのタイトルをcheckに変更し、かつself.button1.config(state='disable')でボタンを無効化します。逆にチェックを外すとボタンのタイトルをuncheckに変更し、self.button1.config(state='active')でボタンを有効にします。26~27行目のshow_statusメソッドは、ボタンクリック時に呼び出され、自身のタイトルをbutton is active!に変更します。

動作確認

それでは実際にコードを実行して動作確認をしてみましょう。

まずは起動時の画面です。

起動時
起動時

チェックボタンとボタンが作成されています。早速チェックボタンにチェックを入れてみましょう。

チェック時
チェック時

チェックを入れると、ボタンのテキストがcheck!に変わり、文字が灰色になりました!見た目は完全に無効化されましたね。見た目はね。

無効化された(ように見える)ボタンをクリックしてみましょう。

クリック時
クリック時

はい。show_statusメソッドが実行されてボタンのテキストが変わってしまいました。最初はここで絶望しましたが、気力を振り絞って解決策を探していると、ウィジェットの無効化を紹介しているサイト等では.bindは使われておらず、ウィジェット作成時にcommandオプションでメソッドを呼び出していることに気が付きました。まさにこれが原因でした。

コードの修正

それでは、上記のコードを修正していきましょう。.bindでメソッドを呼び出すのではなく、ウィジェット作成時にcommandオプションを使用してメソッドと紐づけます。

まず、14行目を、以下の様に修正します。

self.button1 = tkinter.Button(master=self, text='True or False', width=20, command=self.show_status)

次に、15行目を削除またはコメントアウトし、26行目の引数からeventを削除してdef show_status(self):とすればOKです。

修正したコードを実行してボタンを無効化すれば、今度はボタンをクリックしてもshow_statusコードは実行されず、テキストは変化しません。

まとめ

ウィジェットにメソッドを登録する際は、.bindではなくcommandオプションを用いたほうが無難なようです。.bind使用時になぜ無効化が効かないのかは不明ですが、今後調べてみたいと思います。 すぐに解決策が見つかってよかったです。

Pythonで簡単なデスクトップアプリ作成(WordClipper その6)

ある程度wordclipperアプリが形になってきたので、今回はアプリ事態の改善や機能追加ではなく、アプリのpythonスクリプトファイルをexeファイル化をしてみたいと思います。exeファイル化することにより、pythonの環境がないPCでもアプリを使用することができるようになります。pythonスクリプトをexe化する方法はいくつかあるようですが、今回はpyinstallerを使用してみることにしました。

1. インストール

まず、以下のpipコマンドでpyinstallerをインストールしましょう。

pip install pyinstaller

私はpipenvで仮想環境を構築しているので、以下のコマンドでインストールしました。当然ですが、仮想環境を使用している人は仮想環境にpyinstallerをインストールし、仮想環境下で実行しないと動いてくれません。私はこれでしばらくはまりました。ご注意ください。

pipenv install pyinstaller

2. exeファイル化

それでは早速wordclipperアプリのpythonスクリプトファイルをexe化してみます。以下のコマンドで実行できます。簡単ですね!

※いくつかバグ修正をしているので、wordclipper.pyを使う場合は以下から最新版をダウンロードしてください。

pyinstaller wordclipper.py

しばらくすると、同じディレクトリに「build」ディレクトリ、「dist」ディレクトリ、「wordclipper.spec」が生成されます。「dist」ディレクトリの中に「wordclipper」ディレクトリができており、その中を探すと「wordclipper.exe」があります。早速実行してみましょう。以下の様な画面が現れます。

exeファイル実行時
exeファイル実行時

「word_list.csv」が存在しないため、create newボタンのみ作られていますね。(バグ修正では、ファイルが存在しないときの処理を追加しました。)

無事にexeファイル化することができましたが、このexeファイルのみを「dist」ディレクトリから出して使用することはできません。ショートカットを使えば問題ないですが、配布するのはやや面倒です。しかも、実行時にコンソールが開いた状態になるので見栄えがとても悪くなります。そこで、次はpyinstallerのオプションを用いて、exeファイル単体で動き、かつコンソールが開かないようにしたいと思います。

実行方法はとても簡単で、pyinstaller wordclipper.py の後に--onefile--noconsoleの二つのオプションを追記するだけです。

pyinstaller wordclipper.py --onefile --noconsole

実行後に「dist」ディレクトリを確認すると、exeファイル単体が生成されていることが確認できます。実行してみると、コンソールなしで起動でき、かなりすっきりしました。また、exeファイルをどこに移動させても起動できるようになり、簡単に配布できます。

まとめ

pyinstaller、とても便利ですね。exeファイルにすると起動が結構遅くなりますが、個人的にはそれほど気にならないレベルです。それよりも、python環境のない人にも使ってもらえるようになり、いろいろと感想を聞けるのがうれしいですね。