PyInstaller DLL libcairo-2.dll将不会在Fresh Windows 7中加载,但在Windows 10中运行

时间:2017-12-28 06:48:40

标签: windows python-3.x pyinstaller

我在Windows 7中加载libcairo-2.dll时遇到一个非常奇怪的问题。这个脚本在编译之前有效。我正在使用Windows 7进行编译。

这就是我准备编译环境的方法:

setup\python-3.6.4.exe /quiet InstallAllUsers=1 TargetDir=C:\Python
setx path "%path%;C:\Python;"
setup\visualcppbuildtools_full.exe /Passive
C:\Python\python -m pip install pyinstaller
C:\Python\python -m pip install six
C:\Python\python -m pip install cairosvg
pause

这是我想用Windows 7编译的非常简单的main.py:

import ctypes
import os
import sys
#include dlls
pathname = os.path.dirname(os.path.realpath(sys.argv[0]))
ctypes.windll.kernel32.SetDllDirectoryW(pathname)
ctypes.CDLL(pathname+'\\freetype6.dll')
ctypes.CDLL(pathname+'\\libcairo-2.dll')
ctypes.CDLL(pathname+'\\libexpat-1.dll')
ctypes.CDLL(pathname+'\\libfontconfig-1.dll')
ctypes.CDLL(pathname+'\\libpng14-14.dll')
ctypes.CDLL(pathname+'\\zlib1.dll')
print(pathname)
#import stuff
import cairosvg
#make svg file
svg_code = """
    <svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 1000 1000" direction="rtl" xml:lang="fa">
        <title>...</title>
        <desc>...</desc>
        <text x="0" y="10" font-size = "22" font-family="Arial">
            <tspan x="10" dy="1.2em">Test</tspan>
        </text>
    </svg>
"""
#convert
cairosvg.svg2svg(bytestring=svg_code, write_to="converted.svg")
cairosvg.svg2pdf(bytestring=svg_code, write_to="converted.pdf")
cairosvg.svg2png(bytestring=svg_code, write_to="converted.png")
cairosvg.svg2ps (bytestring=svg_code, write_to="converted.ps")

项目文件是:

main.py
freetype6.dll
libcairo-2.dll
libexpat-1.dll
libfontconfig-1.dll
libpng14-14.dll
zlib1.dll

我用这个命令编译:

C:\Python\python -m PyInstaller --add-data *.dll;. --clean --onedir --noupx --name "main-win" main.py

这个编译没有任何错误,我可以在新的Windows 10上运行编译版本。但是当我在新的Windows 7上运行编译版本时,我收到以下错误:

[3000] PyInstaller Bootloader 3.x
[3000] LOADER: executable is C:\Users\Admin\Desktop\main-win_debug\main-win.exe
[3000] LOADER: homepath is C:\Users\Admin\Desktop\main-win_debug
[3000] LOADER: _MEIPASS2 is NULL
[3000] LOADER: archivename is C:\Users\Admin\Desktop\main-win_debug\main-win.exe
[3000] LOADER: No need to extract files to run; setting extractionpath to homepath
[3000] LOADER: SetDllDirectory(C:\Users\Admin\Desktop\main-win_debug)
[3000] LOADER: Already in the child - running user's code.
[3000] LOADER: Python library: C:\Users\Admin\Desktop\main-win_debug\python36.dll
[3000] LOADER: Loaded functions from Python library.
[3000] LOADER: Manipulating environment (sys.path, sys.prefix)
[3000] LOADER: Pre-init sys.path is C:\Users\Admin\Desktop\main-win_debug\base_library.zip;C:\Users\Admin\Desktop\main-win_debug
[3000] LOADER: sys.prefix is C:\Users\Admin\Desktop\main-win_debug
[3000] LOADER: Setting runtime options
[3000] LOADER: Initializing python
[3000] LOADER: Overriding Python's sys.path
[3000] LOADER: Post-init sys.path is C:\Users\Admin\Desktop\main-win_debug\base_library.zip;C:\Users\Admin\Desktop\main-win_debug
[3000] LOADER: Setting sys.argv
[3000] LOADER: setting sys._MEIPASS
[3000] LOADER: importing modules from CArchive
[3000] LOADER: extracted struct
[3000] LOADER: callfunction returned...
[3000] LOADER: extracted pyimod01_os_path
[3000] LOADER: callfunction returned...
[3000] LOADER: extracted pyimod02_archive
[3000] LOADER: callfunction returned...
[3000] LOADER: extracted pyimod03_importers
[3000] LOADER: callfunction returned...
[3000] LOADER: Installing PYZ archive with Python modules.
[3000] LOADER: PYZ archive: out00-PYZ.pyz
[3000] LOADER: Running pyiboot01_bootstrap.py
[3000] LOADER: Running pyi_rth_multiprocessing.py
[3000] LOADER: Running pyi_rth_pkgres.py
[3000] LOADER: Running pyi_rth_win32comgenpy.py
[3000] LOADER: Running main.py
C:\Users\Admin\Desktop\main-win_debug
Traceback (most recent call last):
  File "C:\Users\Admin\Desktop\main.py", line 29, in <module>
  File "<frozen importlib._bootstrap>", line 971, in _find_and_load
  File "<frozen importlib._bootstrap>", line 955, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 665, in _load_unlocked
  File "C:\Python\lib\site-packages\PyInstaller\loader\pyimod03_importers.py", line 631, in exec_module
  File "C:\Python\lib\site-packages\cairosvg\__init__.py", line 29, in <module>
  File "<frozen importlib._bootstrap>", line 971, in _find_and_load
  File "<frozen importlib._bootstrap>", line 955, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 665, in _load_unlocked
  File "C:\Python\lib\site-packages\PyInstaller\loader\pyimod03_importers.py", line 631, in exec_module
  File "C:\Python\lib\site-packages\cairosvg\surface.py", line 24, in <module>
  File "<frozen importlib._bootstrap>", line 971, in _find_and_load
  File "<frozen importlib._bootstrap>", line 955, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 665, in _load_unlocked
  File "C:\Python\lib\site-packages\PyInstaller\loader\pyimod03_importers.py", line 631, in exec_module
  File "C:\Python\lib\site-packages\cairocffi\__init__.py", line 41, in <module>
  File "C:\Python\lib\site-packages\cairocffi\__init__.py", line 38, in dlopen
OSError: dlopen() failed to load a library: cairo / cairo-2
[3000] Failed to execute script main
[3000] LOADER: OK.
[3000] LOADER: Cleaning up Python interpreter.

我在这里包含了源文件: src.zip

我测试了很多不同的东西,我无法弄清楚这一点。有人可以帮助我吗?

感谢。

1 个答案:

答案 0 :(得分:0)

这是一个解决方案。每次程序运行时,都必须在任何cairo调用之前加载下面的代码。最好将它放在程序的最顶层:

import os
import sys
dllpath = os.path.dirname(os.path.realpath(sys.argv[0]))
if dllpath not in os.environ:
    os.environ["PATH"] += os.pathsep + dllpath