一、 前言
在使用nuitka在32位环境下打包ibm_db+sqlachemy遇到的一些问题记录!
二、ibm_db与sqlachemy结合问题
1.需要手动加载ibm_db模块给sqlachemy
报“Can’t load plugin: sqlalchemy.dialects:db2.ibm_db”错误,如下:
File "<string>", line 2, in create_engine
File "C:\Users\Administrator\Desktop\py\DataToolsExe\testDtsRun.dist\sqlalchemy\util\deprecations.py", line 309, in warned
return fn(*args, **kwargs)
File "C:\Users\Administrator\Desktop\py\DataToolsExe\testDtsRun.dist\sqlalchemy\engine\create.py", line 534, in create_engine
entrypoint = u._get_entrypoint()
File "C:\Users\Administrator\Desktop\py\DataToolsExe\testDtsRun.dist\sqlalchemy\engine\url.py", line 661, in _get_entrypoint
cls = registry.load(name)
File "C:\Users\Administrator\Desktop\py\DataToolsExe\testDtsRun.dist\sqlalchemy\util\langhelpers.py", line 343, in load
raise exc.NoSuchModuleError(
sqlalchemy.exc.NoSuchModuleError: Can't load plugin: sqlalchemy.dialects:db2.ibm_db
解决办法:
修改sqlalchemy\util\langhelpers.py文件,加入最后2行
def load(self, name):
if name in self.impls:
return self.impls[name]()
if self.auto_fn:
loader = self.auto_fn(name)
if loader:
self.impls[name] = loader
return loader()
# 在后面报错之前返回idb_db模块,以下修改不适用其他情况,例如mysql,可能MySQL在前面就找到模块了。
if name == 'db2.ibm_db':
from ibm_db_sa.ibm_db import DB2Dialect_ibm_db as r
return r
raise exc.NoSuchModuleError(
"Can't load plugin: %s:%s" % (self.group, name)
)
2.sqlachemy版本问题
由于sqlachemy版本更新比ibm_db、ibm_db_sa更新要快。调用过程出错。
File "<string>", line 2, in create_engine
File "C:\Users\Administrator\Desktop\py\DataToolsExe\testDtsRun.dist\sqlalchemy\util\deprecations.py", line 309, in warned
return fn(*args, **kwargs)
File "C:\Users\Administrator\Desktop\py\DataToolsExe\testDtsRun.dist\sqlalchemy\engine\create.py", line 534, in create_engine
entrypoint = u._get_entrypoint()
File "C:\Users\Administrator\Desktop\py\DataToolsExe\testDtsRun.dist\sqlalchemy\engine\url.py", line 661, in _get_entrypoint
cls = registry.load(name)
File "C:\Users\Administrator\Desktop\py\DataToolsExe\testDtsRun.dist\sqlalchemy\util\langhelpers.py", line 343, in load
from ibm_db_sa.ibm_db import DB2Dialect_ibm_db as r
File "C:\Users\Administrator\Desktop\py\DataToolsExe\testDtsRun.dist\ibm_db_sa\__init__.py", line 22, in <module>
from . import ibm_db, pyodbc, base, zxjdbc
File "C:\Users\Administrator\Desktop\py\DataToolsExe\testDtsRun.dist\ibm_db_sa\zxjdbc.py", line 32, in <module>
from sqlalchemy.connectors.zxJDBC import ZxJDBCConnector
ModuleNotFoundError: No module named 'sqlalchemy.connectors.zxJDBC'
版本适配方法:
ibm_db/ibm_db_sa用最新版本,默认即可;
sqlachemy降版本,例如1.3.19
3.nuitka提示编码错误
使用nuitka进行打包时提示错误(32位,非调试模式);
注:调试模式没有下面错误提示。
File "C:\Users\Administrator\AppData\Local\Programs\Python\Python38-32\lib\site-packages\nuitka\__main__.py", line 142, in <module>
main()
File "C:\Users\Administrator\AppData\Local\Programs\Python\Python38-32\lib\site-packages\nuitka\__main__.py", line 128, in main
MainControl.main()
File "C:\Users\Administrator\AppData\Local\Programs\Python\Python38-32\lib\site-packages\nuitka\MainControl.py", line 916, in main
result, options = compileTree()
File "C:\Users\Administrator\AppData\Local\Programs\Python\Python38-32\lib\site-packages\nuitka\MainControl.py", line 793, in compileTree
loader_code = LoaderCodes.getMetapathLoaderBodyCode(bytecode_accessor)
File "C:\Users\Administrator\AppData\Local\Programs\Python\Python38-32\lib\site-packages\nuitka\codegen\LoaderCodes.py", line 120, in getMetapathLoaderBodyCode
getModuleMetapathLoaderEntryCode(
File "C:\Users\Administrator\AppData\Local\Programs\Python\Python38-32\lib\site-packages\nuitka\codegen\LoaderCodes.py", line 55, in getModuleMetapathLoaderEntryCode
Plugins.encodeDataComposerName(module.getFullName().asString())
File "C:\Users\Administrator\AppData\Local\Programs\Python\Python38-32\lib\site-packages\nuitka\plugins\Plugins.py", line 872, in encodeDataComposerName
name = name.encode("latin1")
UnicodeEncodeError: 'latin-1' codec can't encode characters in position 17-20: ordinal not in range(256)
解决办法:
打开错误提示文件看看里面什么鬼。原文如下:
nuitka\plugins\Plugins.py
def encodeDataComposerName(cls, name):
if str is not bytes:
# Encoding needs to match generated source code output.
name = name.encode("latin1")
修改如下:
def encodeDataComposerName(cls, name):
#这一句逻辑错了,本来是想判断name如果不是bytes类似,就转换为bytes
#if str is not bytes:
if type(name) != bytes:
# Encoding needs to match generated source code output.
# name = name.encode("latin1")
try:
name = name.encode("latin1")
except:
name = name.encode("utf8")