osmnx類をimportしたコードをpyinstallerでexe化しようとしたら発生したエラーとその対処法まとめ

date : 2020/06/25

はじめましてしほみです。

仕事でosmnxをつかったPythonコードを書いてpyinstallerでexeファイル化しようとしたのですが、思いのほかエラーが何件か続いたので記事にまとめてみました。

OSはmacOS、以下はパッケージのバージョンです。

// packages
networkx==2.4
notebook==6.0.3
numpy==1.19.0
osmnx==0.14.1
pandas==1.0.5
PyInstaller==3.6
urllib3==1.25.8

まずこれが動かしたいコードです。(簡略化してます)

import numpy as np
import matplotlib.pyplot as plt
import sys
import pandas as pd
import osmnx as ox
import networkx as nx
import itertools

print('hello world')

ただライブラリをインポートしてるだけですね。

pyinstallerでexe化してみましょう

(ここから長い戦いが始まるとは誰も予想してなかった・・)

pyinstaller test.py --onefile

pyi_rth__tkinter / tk / tcl エラー

エラー文
Traceback (most recent call last):
  File "site-packages/PyInstaller/loader/rthooks/pyi_rth__tkinter.py", line 30, in <module>
FileNotFoundError: Tcl data directory "/var/folders/0k/__dir/T/_MEIaXD01I/tcl" not found.
[33999] Failed to execute script pyi_rth__tkinter
logout

早速エラーが出てきました。

tclがうまくインポートされてないのでマニュアル的にバイナリを読み込むよう.specファイルを修正しましょう

// test.spec
a = Analysis(
    //ADD
    binaries=[
        ('/System/Library/Frameworks/Tcl.framework/Tcl', 'tcl'), 
        ('/System/Library/Frameworks/Tk.framework/Tk', 'tk')
    ], 
)

もう一回変換します。(ここから先はずっと .specファイルでビルドしていきます)

pyinstaller test.spec

datadir エラー

// エラー文
  File "site-packages/pyproj/__init__.py", line 51, in <module>
  File "pyproj/_datadir.pyx", line 6, in init pyproj._datadir
ModuleNotFoundError: No module named 'pyproj.datadir'
[35099] Failed to execute script test
logout

from pyproj import _datadir, datadirを追加します。

// test.py
import numpy as np
import matplotlib.pyplot as plt
import sys
import pandas as pd
import osmnx as ox
import networkx as nx
import itertools
//ADD
from pyproj import _datadir, datadir 

libpng16.16.dylib エラー

この調子でどんどん直していきます

// エラー文
  File "site-packages/fiona/__init__.py", line 84, in <module>
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/PyInstaller/loader/pyimod03_importers.py", line 623, in exec_module
    exec(bytecode, module.__dict__)
  File "site-packages/fiona/collection.py", line 9, in <module>
ImportError: dlopen(/var/folders/0k/__dir/T/__dir/fiona/ogrext.cpython-38-darwin.so, 2): Library not loaded: @loader_path/libpng16.16.dylib
  Referenced from: /private/var/folders/0k/__dir/T/__dir/libgdal.20.dylib
  Reason: Incompatible library version: libgdal.20.dylib requires version 52.0.0 or later, but libpng16.16.dylib provides version 38.0.0
[36001] Failed to execute script test
logout

どうやらライブラリのバージョンがリンクできてないっぽいですね

brew update && brew upgrade しても解消できなかった場合は手動でやってあげます。

https://qiita.com/omuram/items/7be71191e3d1b41c8835 を参考にライブラリの場所を確認し、sudo install_name_tool -change "ライブラリの名前" "リンクしたいライブラリの場所" エラー文にでてきた.soファイルでリンクしなおします

sudo install_name_tool -change "@loader_path/libpng16.16.dylib"  "/opt/X11/lib/libpng16.16.dylib" /Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/fiona/ogrext.cpython-38-darwin.so

バージョンダブり防止に下の行を a = Analysis()の後に追加します

// test.spec
//ADD
a.binaries = a.binaries - TOC([('libpng16.16.dylib',None,None)])

この方法があってるかどうかは微妙ですが


fiona._shim エラー

pyimod03_importers.py", line 623, in exec_module
    exec(bytecode, module.__dict__)
  File "site-packages/fiona/collection.py", line 9, in <module>
  File "fiona/ogrext.pyx", line 1, in init fiona.ogrext
ModuleNotFoundError: No module named 'fiona._shim'
[36952] Failed to execute script test
logout

from fiona import _shim, schemaを追加して半ば無理矢理モジュールを入れます。

// test.py
import numpy as np
import matplotlib.pyplot as plt
import sys
import pandas as pd
//ADD
from fiona import _shim, schema
import osmnx as ox
import networkx as nx
import itertools
from pyproj import _datadir, datadir

datasets エラー

エラー文を保存してませんでしたが、geopandasのdatasetsは .specファイルでマニュアル的にビルドできないとのことなので site-packages/geopandas/__init__.py", line 13geopandas.datasetsをインポートするところをコメントアウトします

# commentout 
# import geopandas.datasets  # noqa

_cnames エラー

エラー文
packages/PyInstaller/loader/pyimod03_importers.py", line 623, in exec_module
    exec(bytecode, module.__dict__)
  File "site-packages/branca/__init__.py", line 7, in <module>
  File "<frozen importlib._bootstrap>", line 991, in _find_and_load
  File "<frozen importlib._bootstrap>", line 975, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 671, in _load_unlocked
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/PyInstaller/loader/pyimod03_importers.py", line 623, in exec_module
    exec(bytecode, module.__dict__)
  File "site-packages/branca/colormap.py", line 25, in <module>
FileNotFoundError: [Errno 2] No such file or directory: '/var/folders/0k/__dir/T/__dir/branca/_cnames.json'
[37930] Failed to execute script test
logout

site-packages\branca\element.pyを以下に変更します。

\branca\element.py
# commment out
# ENV = Environment(loader=PackageLoader('folium', 'templates'))

import os, sys
from jinja2 import FileSystemLoader
if getattr(sys, 'frozen', False):
    templatedir = sys._MEIPASS
else:
    templatedir = os.path.dirname(os.path.abspath(__file__))
ENV = Environment(loader=FileSystemLoader(templatedir + '/templates'))

a = Analysis()に以下を追加します。

//test.spec
a = Analysis(
    datas=[
        //追加
        ("/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/branca/*.json","branca"),
        ("/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/branca/templates","templates"),
    ],
)

ついに

hello world
logout

できました〜

長い道のりでした。 地理情報系のライブラリ/geopandas/osmnx/fionaを使おうとすると起きるようです。 バージョン問題には頭かかえますね、ではでは

引用

http://eeko-amaryllis.hatenablog.com/entry/2016/07/28/181303

https://stackoverflow.com/questions/55824830/i-get-error-no-module-named-pyproj-datadir-after-i-made-py-to-exe-with-py

https://stackoverflow.com/questions/46246649/manually-specify-library-when-pyinstaller-sees-conflicting-versions

https://stackoverflow.com/questions/56804095/pyinstaller-stopiteration-error-when-i-import-geopandas

https://stackoverflow.com/questions/54836440/branca-python-module-is-unable-to-find-2-essential-json-files-when-running-an-ex

https://qiita.com/omuram/items/7be71191e3d1b41c8835