pyinstallerで作成したexeファイルで発生するpkg_resources.DistributionNotFoundの対処法について

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 236

tomy-c

score 20

pytonで最新バージョンのgoogle翻訳APIを組み込んだ実行ファイルを作成したいという目的の元、
下記の環境にてgoogle translate api のサンプルプログラムを作成しました。

・python3.7 64bit(公式より取得)
・VisualStudioCode (拡張機能でPythonの環境+日本語化をしています。インタプリタは上のpython3.7 64bit版です) 
・powershell
・google translate api v3beta1

発生している問題・エラーメッセージ

現在の状態として
・コンソールから直接実行した場合
・VSCodeから実行した場合
上記の場合は実行結果は正常に動作します。

ですが、pyinstallerを使用し、出力されたexeファイルを実行した場合下記のエラーが発生し、
動作しませんでした。

pyinstaller で出力した実行ファイルで正常に動作させたい場合どうすれば宜しいのでしょうか?

PS C:\Users\"ユーザー名”\Documents\google_translate_test1\dist> .\main.exe
['C:\\Users\\"ユーザー名”\\AppData\\Local\\Temp\\_MEI225602\\base_library.zip',
 'C:\\Users\\"ユーザー名”\\AppData\\Local\\Temp\\_MEI225602',
 'C:\\Users\\"ユーザー名”\\Documents\\google_translate_test1\\dist\\lib']
Traceback (most recent call last):
  File "google_translate_test1\main.py", line 41, in <module>
  File "<frozen importlib._bootstrap>", line 983, in _find_and_load
  File "<frozen importlib._bootstrap>", line 967, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 677, in _load_unlocked
  File "c:\users\"ユーザー名”\appdata\local\programs\python\python37\lib\site-packages\PyInstaller\loader\pyimod03_importers.py", line 627, in exec_module
    exec(bytecode, module.__dict__)
  File "google_translate_test1\lib\google\cloud\translate_v3beta1\__init__.py", line 20, in <module>
  File "<frozen importlib._bootstrap>", line 983, in _find_and_load
  File "<frozen importlib._bootstrap>", line 967, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 677, in _load_unlocked
  File "c:\users\"ユーザー名”\appdata\local\programs\python\python37\lib\site-packages\PyInstaller\loader\pyimod03_importers.py", line 627, in exec_module
    exec(bytecode, module.__dict__)
  File "site-packages\google\cloud\translate_v3beta1\__init__.py", line 21, in <module>
  File "<frozen importlib._bootstrap>", line 983, in _find_and_load
  File "<frozen importlib._bootstrap>", line 967, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 677, in _load_unlocked
  File "c:\users\"ユーザー名”\appdata\local\programs\python\python37\lib\site-packages\PyInstaller\loader\pyimod03_importers.py", line 627, in exec_module
    exec(bytecode, module.__dict__)
  File "site-packages\google\cloud\translate_v3beta1\gapic\translation_service_client.py", line 47, in <module>
  File "site-packages\pkg_resources\__init__.py", line 481, in get_distribution
  File "site-packages\pkg_resources\__init__.py", line 357, in get_provider
  File "site-packages\pkg_resources\__init__.py", line 900, in require
  File "site-packages\pkg_resources\__init__.py", line 786, in resolve
pkg_resources.DistributionNotFound: The 'google-cloud-translate' distribution was not found and is required by the application


pipで取得してきたgoogle-cloud-translateに含まれている
google-cloud-translateに対して DistributionNotFoundが発生しているため、pyinstallerでexeファイルを作成時に正常なpathが設定できていないと考えています。

該当のソースコード

※実験用プログラムの為作りが荒いことをお詫びします。
また、実行するためにはGoogleCloudPlatformに登録後クレジットカード等の決済手段を登録し、GCPよりプロジェクトの作成→秘密鍵.jsonの発行が必要になります。これらはサンプルソースコードの1行目のurlに手順が記載されてます。翻訳が中途半端ですが。

# https://cloud.google.com/translate/docs/quickstart-client-libraries-v3?hl=ja
#  pip install --upgrade google-cloud-translate -t "プロジェクトディレクトリ/lib"

# クライアントAPI gRPC通信している?
# VSCodeではインタプリタを別途インストールしたpythonに変更しておくこと
# (コンソールでの実行とVSCodeではデフォルトのインタプリタが異なり、ライブラリパスの参照先も異なる)
# (pip でライブラリをinstallしている場合は特に影響がある? ※未確認)
# https://code.visualstudio.com/docs/python/environments
# VSCode → python 32bit
# Ctrl + Shift + P → "Python: Select Interpreter" → Python3.7.4 64bit 

#デバッグ設定 lunch.json
# https://stackoverflow.com/questions/54160948/how-to-fix-the-path-attribute-not-found-error-for-packages-installed-by-pi
#{
#     "name": "Python: Module",
#     "type": "python",
#     "request": "launch",
#     "module": "main",             #エントリーポイントファイル名 (拡張子不要)
#     "console": "integratedTerminal"
# },

# 作成したプロジェクトの秘密鍵をインポート(環境変数に登録する方法は駄目だった)
import inspect  # デバッグ用
import os
import sys

#ライブラリへのパスを追加
# ROOTPATH = os.path.dirname(__file__)
ROOTPATH = os.path.dirname(sys.argv[0]) #pytinstaller では __file__は使用不可能
LIBPATH = os.path.join(ROOTPATH, 'lib')
sys.path.append(LIBPATH)

# python上で環境変数を追加(google core import前に実行)
os.environ['GOOGLE_APPLICATION_CREDENTIALS'] = 'プロジェクト作成時にダウンロードできる秘密鍵.json'

# デバッグ用(読み込んでいるディレクトリの確認)
import pprint
pprint.pprint(sys.path)

# 無料なのはversion3のβ1版のみ
from lib.google.cloud import translate_v3beta1 as translate
client = translate.TranslationServiceClient()




text = u'Hello, world!'
location = 'global'


parent = client.location_path('発行したプロジェクトのID', location)

# 国コードは以下参照
# https://ja.wikipedia.org/wiki/ISO_3166-1
response = client.translate_text(
    parent=parent,
    contents=[text],
    mime_type='text/plain',  # mime types: text/plain, text/html
    source_language_code='en-US',
    target_language_code='fr')

# ver3Beta1では一部言語の結果が8進数で返ってくる模様・・・→翻訳結果の指定方法がGoogle公式のサンプル通りでは出ず、
# translation.translated_textに翻訳結果が格納されていた。
for translation in response.translations:

#   オブジェクトの中身表示
#   print( inspect.getmembers( object) )    
    print(u'Translated Text: {}'.format(translation.translated_text))

#入力待ち
# input()

sys.path比較

コンソールからpyファイルを直接実行時に出力されたsys.path

['C:\\Users\\"ユーザー名”\\Documents\\google_translate_test1',
 'C:\\Users\\"ユーザー名”\\AppData\\Local\\Programs\\Python\\Python37\\python37.zip',      
 'C:\\Users\\"ユーザー名”\\AppData\\Local\\Programs\\Python\\Python37\\DLLs',
 'C:\\Users\\"ユーザー名”\\AppData\\Local\\Programs\\Python\\Python37\\lib',
 'C:\\Users\\"ユーザー名”\\AppData\\Local\\Programs\\Python\\Python37',
 'C:\\Users\\"ユーザー名”\\AppData\\Roaming\\Python\\Python37\\site-packages',
 'C:\\Users\\"ユーザー名”\\AppData\\Local\\Programs\\Python\\Python37\\lib\\site-packages',
 '.\\lib']

pyinstallerで作成したexeが出力したsys.path

 ['C:\\Users\\"ユーザー名”\\Documents\\google_translate_test1\\dist\\main\\base_library.zip',
 'C:\\Users\\"ユーザー名”\\Documents\\google_translate_test1\\dist\\main',
 'lib',
 '.\\lib']


※pyinstaller側は圧倒的にpathが不足している

補足情報 

プロジェクトの構成は以下のようになっています

├─.vscode    #VSCodeのデバッグ用設定とかが入っている
├─build      #pyinstaller 実行時のビルド
├─dist       #pyinstaller 実行時の実行ファイル格納場所
└─lib        #pipで入手したgoogle-cloud-translateクライアントライブラリ格納場所(作った)
   ├─bin
   ├─cachetools
   ├─cachetools-3.1.1.dist-info
   ├─certifi
   ├─certifi-2019.6.16.dist-info
   ├─chardet
   ├─chardet-3.0.4.dist-info
   ├─google
   │  ├─auth
   │  ├─cloud
   │  │  ├─translate_v2
   │  │  └─translate_v3beta1
   │  ├─logging
   │  ├─longrunning
   │  ├─oauth2
   │  ├─protobuf
   │  ├─rpc
   │  └─type
   ├─googleapis_common_protos-1.6.0-py3.7.egg-info
   ├─google_api_core-1.14.0.dist-info
   ├─google_auth-1.6.3.dist-info
   ├─google_cloud_core-1.0.2.dist-info
   ├─google_cloud_translate-1.6.0.dist-info
   ├─grpc
   ├─grpcio-1.22.0.dist-info
   ├─idna
   ├─idna-2.8.dist-info
   ├─pkg_resources
   ├─protobuf-3.9.0.dist-info
   ├─pyasn1
   ├─pyasn1-0.4.5.dist-info
   ├─pyasn1_modules
   ├─pyasn1_modules-0.2.5.dist-info
   ├─pytz
   ├─pytz-2019.1.dist-info
   ├─requests
   ├─requests-2.22.0.dist-info
   ├─rsa
   ├─rsa-4.0.dist-info
   ├─setuptools
   ├─setuptools-41.0.1.dist-info
   ├─six-1.12.0.dist-info
   ├─urllib3
   └─urllib3-1.25.3.dist-info
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

check解決した方法

0

PyinstallerでFirestoreを使ったPythonスクリプトをEXE化する際のTips
https://qiita.com/akitooo/items/eb82a5f335d8ca9c9faf

google translate とは違いますが、上記の内容を元に main.pyファイルと同じディレクトリに生成されていたmain.specファイルを開き下記のpathexに必要なライブラリのパスを全部記述した状態でpyinstallerを実行することで少なくとも今回発生したエラーは解消されました。 ※別のエラーが発生し、結局動いていないのでこの方法が正しいかは確証が持てませんが。(その問題に対しては別途質問をする予定です。)

# -*- mode: python ; coding: utf-8 -*-

block_cipher = None


a = Analysis(['main.py'],
             pathex=['コンソール実行時に出ていたsys.pathを全部記述'],
             binaries=[],
             datas=[],
             hiddenimports=[],
             hookspath=[],
             runtime_hooks=[],
             excludes=[],
             win_no_prefer_redirects=False,
             win_private_assemblies=False,
             cipher=block_cipher,
             noarchive=False)
pyz = PYZ(a.pure, a.zipped_data,
             cipher=block_cipher)
exe = EXE(pyz,
          a.scripts,
          a.binaries,
          a.zipfiles,
          a.datas,
          [],
          name='main',
          debug=False,
          bootloader_ignore_signals=False,
          strip=False,
          upx=True,
          upx_exclude=[],
          runtime_tmpdir=None,
          console=True )

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.21%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる