LoginSignup
58

More than 5 years have passed since last update.

pyinstallerの*.specファイル作成法。

Last updated at Posted at 2016-06-10

作成されたpython scriptをpyinstallerを用いてMacOSのアプリを作れます。

最初僕はpy2appを使用しましたが結果ファイルサイズが以下のように違いました。
- Py2appの結果:35MB
- Pyinstallerの結果:25MB
Pyinstallerを使わないわけがないでしょう。
インストールはPIPで可能になりまして。(昨年はできませんでした)

pip install pyinstaller

それで完了

pyinstallerの駆動は*.specファイルを通じてするのがお勧めです。

specファイルの基本構造は下のようです。

# -*- mode: python -*-
# filename = Main.spec

a = Analysis(['Main.py'],
             pathex=['/Users/.../ProgramNameDir'],
             hiddenimports=[],
             hookspath=None,
             runtime_hooks=None)
pyz = PYZ(a.pure)
exe = EXE(pyz,
          a.scripts,
          a.binaries,
          a.zipfiles,
          a.datas,
          name='Main',
          debug=False,
          strip=None,
          upx=True,
          console=False , icon='mainIcon.ico')
app = BUNDLE(exe,
             name='Main.app',
             icon='mainIcon.ico')

この場合はmain.pyを読んでMain.appを作ります。iconはmainIcon.icoをかぶります。

Main.pyは ”/Users/.../ProgramNameDir”に存在し、その下の "./lib"のlibファイルを参考しています。なので *.specファイルが"./lib"を認識できるように少し修正します。

# -*- mode: python -*-
# filename = Main.spec

### 個人の./libsを認識するためのコード ###
import sys 
myLibPath = './libs'
sys.path.append(myLibPath)
############################

a = Analysis(['Main.py'],
             pathex=['/Users/.../ProgramNameDir'],
             hiddenimports=[],
             hookspath=None,
             runtime_hooks=None)
pyz = PYZ(a.pure)
exe = EXE(pyz,
          a.scripts,
          a.binaries,
          a.zipfiles,
          a.datas,
          name='Main',
          debug=False,
          strip=None,
          upx=True,
          console=False , icon='mainIcon.ico')
app = BUNDLE(exe,
             name='Main.app',
             icon='mainIcon.ico')

もう一つの問題があります。Main.pyでは /Users/.../ProgramNameDir/img内のイメージ・ファイルをつかいます。これはsys.path.appendで追加しても最終のアプリでは読めません。イメージ・ファイルをハンドリング仕組みが違うからです。

pyinstallerで作られたアプリが駆動する際、必要なファイル(イメージ・ファイルなど)は臨時フォルダ(temp folder)内「_MEIPASS」という場所でコピーします。だから*.pyコード内に「_MEIPASS」を認識させる必要があります。

Main.pyでこの関数を追加します。

def resource_path(relative):
  if hasattr(sys, "_MEIPASS"):
      return os.path.join(sys._MEIPASS, relative)
  return os.path.join(relative)

そしてコード内のイメージ参照こどを変換します。
例え:
"./img/Title.png" --> resource_path("./img/Title.png")

*.specファイルにはTree()を追加します。

# -*- mode: python -*-
#filename = Main.spec
import sys 
myLibPath = './libs'
sys.path.append(myLibPath)
a = Analysis(['Main.py'],
             pathex=['/Users/.../ProgramNameDir'],
             hiddenimports=[],
             hookspath=None,
             runtime_hooks=None)
pyz = PYZ(a.pure)
exe = EXE(pyz,
Tree('img',prefix='img'), #<--追加するイメージがあるフォルダ名
          a.scripts,
          a.binaries,
          a.zipfiles,
          a.datas,
          name='Main',
          debug=False,
          strip=None,
          upx=True,
          console=False , icon='mainIcon.ico')
app = BUNDLE(exe,
             name='Main.app',
             icon='mainIcon.ico')

僕はMacBook proを使っています。即ちRetina Displayを使っています。pyinstallerで作られたアプリをそのまま作るとRetina Displayの上にはメッセージ・ボックスとかダイアログが滲んで見えるので醜いです。
それを解決するためBUNDLEにinfo_plistを追加します。

# -*- mode: python -*-
#filename = Main.spec
import sys 
myLibPath = './libs'
sys.path.append(myLibPath)
a = Analysis(['Main.py'],
             pathex=['/Users/.../ProgramNameDir'],
             hiddenimports=[],
             hookspath=None,
             runtime_hooks=None)
pyz = PYZ(a.pure)
exe = EXE(pyz,
Tree('img',prefix='img'), 
          a.scripts,
          a.binaries,
          a.zipfiles,
          a.datas,
          name='Main',
          debug=False,
          strip=None,
          upx=True,
          console=False , icon='mainIcon.ico')
app = BUNDLE(exe,
             name='Main.app',
        info_plist={ 'NSHighResolutionCapable': 'True'}, #<-- Option for High Resolution
             icon='mainIcon.ico')

これで大体におわりです。
pyinstaller Main.spec
でアプリができます。

py2exeとかpy2appの場合は事例がずいぶんあるけどpyinstallerの場合はあんまりないので整理のため記録しました。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
58