ImportError: Ошибка загрузки DLL: указанный модуль не найден - IBM DB2 - PullRequest
0 голосов
/ 25 апреля 2019

Я знаю, что было много людей с такой же проблемой, но вот моя ситуация, в которой я не смог найти точно такую ​​же проблему. Я строю исполняемый файл с pyinstaller, и я получаю importError. Я использую пакет ibm_db для подключения к базе данных IBM DB2 и вставляю в таблицу, используя метод pandas to_sql. Я использовал pyinstaller в своей программе до того, как добавил код SQL, так что я почти уверен, что это как-то связано с моими попытками подключиться к DB2, но, судя по всему, я не могу этого понять.

Я получаю много предупреждений и информационных сообщений, когда запускаю pyinstaller, но не вижу ошибок, которые я вижу. Я получаю ошибку только после того, как пытаюсь выполнить исполняемый файл, созданный pyinstaller.

Я пытался запустить его в виртуальной среде, чтобы попытаться изолировать проблему, но я не настолько знаком с виртуальными средами, поэтому я перестал пытаться использовать это.

Traceback (most recent call last):
  File "rebate_gui_sql.py", line 9, in <module>
  File "c:\users\dt24358\lib\site-packages\PyInstaller\loader\pyimod03_importers.py", line 627, in exec_module
    exec(bytecode, module.__dict__)
  File "site-packages\ibm_db.py", line 10, in <module>
  File "site-packages\ibm_db.py", line 9, in __bootstrap__
  File "imp.py", line 342, in load_dynamic
ImportError: DLL load failed: The specified module could not be found.
[11020] Failed to execute script rebate_gui_sql

Обновление: 01.05.2009 из комментария ниже, вот моя простая программа

import pandas as pd
from tkinter import *
from tkinter import ttk
import ibm_db
import ibm_db_dbi as db
from sqlalchemy import create_engine

class Application(Frame):

    def __init__(self, master):
        ttk.Frame.__init__(self, master)  
        self.master = master
        self.run_process()

    def run_process(self):
        engine = create_engine("db2+ibm_db://userid:password@url:port/database")
        conn = engine.connect()
        print("Connected to " + str(engine))

        sql = '''
            Select *
            from rebteam.pd5
            fetch first row only
            '''

        df = pd.read_sql(sql, conn)
        print(df)

        df.to_csv(r'c:\users\dt24358\scripts\pricing tool\GUI_SQL\test.csv', index=False)
        self.result_label = Label(root, text="Select of PD5 Successful", bg="light green", width=80, justify=LEFT)
        self.result_label.grid(row=0,columnspan=2)

root=Tk()
root.title("Rebate Bid Data Upload")
root.configure(background="light green")
app = Application(root)
root.mainloop()

Ответы [ 2 ]

1 голос
/ 02 мая 2019

Этот ответ относится к следующим версиям:

pyinstaller 3.4  
setuptools 41.0.1 
ibm_db 3.0.1
ibm_db_sa 0.3.4
sqlalchemy 1.3.3

Здесь есть две отдельные проблемы.

Непосредственная проблема (ошибка ImportError) - сбой при загрузке ibm_db.dll

ImportError происходит из-за того, что pyinstaller не копирует внешние (не python) библиотеки в пакет, если вы явно не запросите это.

Опция pyinstaller --add-binary дает обходной путь для этого ImportError, см. Пример ниже.

Если ваш скрипт python использует SQLAlchemy для доступа к Db2, то вы можете увидеть второй симптом во время выполнения послездание с pyinstaller.Признак времени выполнения: либо

"sqlalchemy.exc.NoSuchModuleError: Не удается загрузить плагин: sqlalchemy.dialects: ibm_db_sa"

или

"sqlalchemy.exc.NoSuchModuleError: Не удается загрузить плагин: sqlalchemy.dialects: db2.ibm_db"

(в зависимости от префикса для URL-адреса, данного для create_engine ())

Этот симптом sqlalchemy.exe.NoSuchModuleError не относится к Db2, но может влиять на другие базы данных при использовании через SQLAlchemy с диалектом external (Db2, teradata, Snowke, Presto,...).Базы данных, использующие внутренние диалекты SQLAlchemy, могут просто работать "из коробки".

Здесь есть один обходной путь, возможны и другие обходные пути.

Внешние диалекты SQLAlchemy используют pkg_resources entry_points, чтобы позволить SQLAlchemy использовать их, ноpyinstaller пока не может справиться с этим без вашей помощи.Такая информация точки входа является своего рода метаданными о модуле.

Этот обходной путь использует ловушки pyinstaller для сбора метаданных соответствующих модулей и сообщает pyinstaller каталог (или каталоги), которые содержат эти файлы ловушек.Для Db2 с SQLAlchemy необходимы три файла хуков, hook-ibm_db.py, hook-ibm_db_sa.py, hook-sqlalchemy.py.Я решил поместить эти файлы ловушек в тот же каталог, что и скрипт Python моего исходного файла.

Содержимое каждого из этих файлов состоит из двух строк, а содержимое отличается только именем модуля, содержащегося в нем.Вот пример одного из файлов hook-sqlalchemy.py (для двух других необходимых файлов просто замените имя модуля соответствующим образом):

from PyInstaller.utils.hooks  import  copy_metadata

datas = copy_metadata('sqlalchemy')

Чтобы добавить ibm_db.dll через --add-binary method, вы можетелибо используйте параметр командной строки для pyinstaller, либо отредактируйте файл спецификации.

Итак, для обоих обходных путей предположим, что ваш ibm_db.dll находится в этом каталоге:

%LOCALAPPDATA%\programs\python\python37\lib\site-packages\ibm_db_dlls

и вы создаете переменнуючтобы указать на это местоположение:

> set ibm_db_path=%LOCALAPPDATA%\programs\python\python37\lib\site-packages\ibm_db_dlls

Для командного файла MS-Windows (с использованием ^ в качестве символа продолжения строки) пример командной строки pyinstaller для обработки обоих упомянутых выше обходных путей:

pyinstaller -y ^
--additional-hooks-dir=. ^
--hidden-import ibm_db_sa.ibm_db ^
--hidden-import ibm_db_dbi ^
--hidden-import ibm_db ^
--add-binary  %LOCALAPPDATA%\Programs\Python\Python37\Lib\site-packages\ibm_db_dlls\ibm_db.dll;.\ibm_db_dlls ^
 your_script.py

Примечания:

  • Если ваш скрипт на python явно импортирует модули, вам не нужно указывать их через опции --hidden-import (купитьвам все еще нужны хуки).

  • Файл ibm_db.dll должен находиться в подкаталоге ibm_db_dlls вашего комплекта, что является причиной для указания этого места назначения в параметре --add-binary.

  • Если вы собираете для Linux / Unix вместо ^.используйте \ как символ продолжения строки как обычно.

0 голосов
/ 10 мая 2019

Спасибо за ваш вопрос и ответ. Я встречался с такой же ситуацией в Windows7 Python3.7 ibm-db 3.0.1
с вашей подсказкой , Я думаю, что причина в том, что exe не может найти * .dll в clidriver \ bin и ibm_db.dll, и решить его с помощью аналогичного метода в два этапа

Frist: так же, как вы, добавьте каталог clidriver в системный путь

**\site-packages\clidriver\bin

Второй pack с аргументом --add-binary

 Pyinstaller --add-binary **\Lib\site-packages\ibm_db_dlls\ibm_db.dll;.\ibm_db_dlls myproject.py

Тогда все нормально!

аналогичный вопрос: Исполняемый файл PyQt5 аварийно завершает работу с отсутствующей DLL

...