cx_Freeze 与 GeoPandas geos_c.dll

cx_Freeze with GeoPandas geos_c.dll

我在尝试导出 python 文件时遇到问题。通常我在 conda 环境中使用 PyInstaller,但我读到 cx_Freeze 更容易与 geopandas 结合使用。

我生成了一个测试脚本:

# test.py
import numpy as np
import geopandas as gpd
import sys

from pyproj import _datadir, datadir

print("Test script:")
print(f"Executable {sys.executable}")
print("Read numpy list")
x = np.linspace(0, 10, 11)
print(x)

这个脚本运行良好,我使用的是conda环境。带有 from pyproj import _datadir, datadir 的行是为了防止 GeoPandas 的导入错误。

这是我的设置脚本:

# setup.py
import cx_Freeze

cx_Freeze.setup(
        name = "test",
        version = "0.1",
        description = "test import geopandas",
        executables = [cx_Freeze.Executable("test.py")]
        )

我还尝试了另一个设置脚本:

import cx_Freeze
import sys
import os 

PYTHON_INSTALL_DIR = os.path.dirname(sys.executable)
os.environ['TCL_LIBRARY'] = os.path.join(PYTHON_INSTALL_DIR, 'tcl', 'tcl8.6')
os.environ['TK_LIBRARY'] = os.path.join(PYTHON_INSTALL_DIR, 'tcl', 'tk8.6')

include_files = [(os.path.join(PYTHON_INSTALL_DIR, 'DLLs', 'tk86t.dll'), os.path.join('lib', 'tk86t.dll')),
                 (os.path.join(PYTHON_INSTALL_DIR, 'DLLs', 'tcl86t.dll'), os.path.join('lib', 'tcl86t.dll'))]

packages = ["numpy", "tkinter",
            "geopandas", "shapely", "fiona"]

base = None
if sys.platform == "win32":
    base = "Win32GUI"

executables = [cx_Freeze.Executable("test.py", base=base)]

cx_Freeze.setup(
        name = "Network_Analyst",
        options = {"build_exe": {"packages":packages,
                                 "include_files":include_files}},
        version = "0.1",
        description = "Network analyst",
        executables = executables
        )

但是我得到了同样的错误。

我也结合 PyInstaller 尝试过这个答案:

但这没有用。

我也不明白的是错误是:

FileNotFoundError: Could not find module 'C:\Projecten\ERTMS\python\temp\Library\bin\geos_c.dll' (or one of its dependencies). Try using the full path with constructor syntax

但是包是在 /python/temp/build/exe.wim-amd64-3.9 中构建的。我在 temp 下创建了一个文件夹,并将 geos_c.dll 复制到该位置,因此路径 /python/temp/Library/bin/geos_c.dll 确实存在,但可执行文件抛出相同的错误。

这些是安装在我的 conda 环境中的包,我使用的是 windows 11.

# packages in environment at \anaconda3\envs\test_env:
#
# Name                    Version                   Build  Channel
altgraph                  0.17               pyhd3eb1b0_0
attrs                     21.2.0             pyhd3eb1b0_0
blas                      1.0                         mkl
bottleneck                1.3.2            py39h7cc1a96_1
brotli                    1.0.9                ha925a31_2
bzip2                     1.0.8                he774522_0
ca-certificates           2021.10.26           haa95532_2
certifi                   2021.10.8        py39haa95532_0
cfitsio                   3.470                he774522_6
click                     7.1.2              pyhd3eb1b0_0
click-plugins             1.1.1              pyhd3eb1b0_0
cligj                     0.7.2            py39haa95532_0
curl                      7.78.0               h86230a5_0
cx-freeze                 6.8.4                    pypi_0    pypi
cx_freeze                 6.8.4            py39hb82d6ee_0    conda-forge
cycler                    0.10.0           py39haa95532_0
expat                     2.4.1                h6c2663c_2
fiona                     1.8.13.post1     py39h758c064_0
fonttools                 4.25.0             pyhd3eb1b0_0
freetype                  2.10.4               hd328e21_0
freexl                    1.0.6                h2bbff1b_0
future                    0.18.2           py39haa95532_1
gdal                      3.0.2            py39hb978731_1
geopandas                 0.9.0                      py_1
geopandas-base            0.9.0                      py_1
geos                      3.8.0                h33f27b4_0
geotiff                   1.6.0                h5770a2b_0
hdf4                      4.2.13               h712560f_2
hdf5                      1.10.6               h7ebc959_0
icc_rt                    2019.0.0             h0cc432a_1
importlib-metadata        4.8.1            py39haa95532_0
intel-openmp              2021.4.0          haa95532_3556
joblib                    1.1.0              pyhd3eb1b0_0
jpeg                      9d                   h2bbff1b_0
kealib                    1.4.14               hde4a422_0
kiwisolver                1.3.1            py39hd77b12b_0
krb5                      1.19.2               h5b6d351_0
libcurl                   7.78.0               h86230a5_0
libgdal                   3.0.2                ha1b3edf_1
libiconv                  1.15                 h1df5818_7
libnetcdf                 4.6.1                hf59b723_4
libpng                    1.6.37               h2a8f88b_0
libpq                     12.2                 hb652d5d_1
libspatialindex           1.9.3                h6c2663c_0
libspatialite             4.3.0a               h7ffb84d_0
libssh2                   1.9.0                h7a1dbc1_1
libtiff                   4.2.0                hd0e1b90_0
libwebp                   1.2.0                h2bbff1b_0
libxml2                   2.9.12               h0ad7f3c_0
lz4-c                     1.9.3                h2bbff1b_1
m2w64-expat               2.1.1                         2
m2w64-gcc-libgfortran     5.3.0                         6
m2w64-gcc-libs            5.3.0                         7
m2w64-gcc-libs-core       5.3.0                         7
m2w64-gettext             0.19.7                        2
m2w64-gmp                 6.1.0                         2
m2w64-libiconv            1.14                          6
m2w64-libwinpthread-git   5.0.0.4634.697f757               2
m2w64-xz                  5.2.2                         2
macholib                  1.14               pyhd3eb1b0_1
mapclassify               2.4.3              pyhd3eb1b0_0
matplotlib-base           3.4.3            py39h49ac443_0
mkl                       2021.4.0           haa95532_640
mkl-service               2.4.0            py39h2bbff1b_0
mkl_fft                   1.3.1            py39h277e83a_0
mkl_random                1.2.2            py39hf11a4ad_0
msys2-conda-epoch         20160418                      1
munch                     2.5.0              pyhd3eb1b0_0
munkres                   1.1.4                      py_0
networkx                  2.6.3              pyhd3eb1b0_0
numexpr                   2.7.3            py39hb80d3ca_1
numpy                     1.21.2           py39hfca59bb_0
numpy-base                1.21.2           py39h0829f74_0
olefile                   0.46               pyhd3eb1b0_0
openjpeg                  2.4.0                h4fc8c34_0
openssl                   1.1.1l               h2bbff1b_0
pandas                    1.3.4            py39h6214cd6_0
pefile                    2019.4.18                  py_0
pillow                    8.4.0            py39hd45dc43_0
pip                       21.2.4           py39haa95532_0
postgresql                12.2                 hb652d5d_1
proj                      6.2.1                h9f7ef89_0
pycryptodome              3.10.1           py39h2bbff1b_0
pyinstaller               3.6              py39h8cc25b3_6
pyparsing                 3.0.4              pyhd3eb1b0_0
pyproj                    2.6.1.post1      py39h593ac45_1
python                    3.9.0                h6244533_2
python-dateutil           2.8.2              pyhd3eb1b0_0
python_abi                3.9                      2_cp39    conda-forge
pytz                      2021.3             pyhd3eb1b0_0
pywin32                   228              py39hbaba5e8_1
pywin32-ctypes            0.2.0           py39haa95532_1000
rtree                     0.9.7            py39h2eaa2aa_1
scikit-learn              1.0.1            py39hf11a4ad_0
scipy                     1.7.1            py39hbe87c03_2
setuptools                58.0.4           py39haa95532_0
shapely                   1.7.1            py39h06580b3_0
six                       1.16.0             pyhd3eb1b0_0
sqlite                    3.36.0               h2bbff1b_0
threadpoolctl             2.2.0              pyh0d69192_0
tiledb                    2.2.9                hf84e3da_0    conda-forge
tk                        8.6.11               h2bbff1b_0
tornado                   6.1              py39h2bbff1b_0
tzdata                    2021e                hda174b7_0
vc                        14.2                 h21ff451_1
vs2015_runtime            14.27.29016          h5e58377_2
wheel                     0.37.0             pyhd3eb1b0_1
wincertstore              0.2              py39haa95532_2
xerces-c                  3.2.3                ha925a31_0
xz                        5.2.5                h62dcd97_0
zipp                      3.6.0              pyhd3eb1b0_0
zlib                      1.2.11               h62dcd97_4
zstd                      1.4.9                h19a0ad4_0

我在引用其他库和二进制文件以及使用 tkinter 时遇到了同样的问题。我在 windows 10 上用 miniconda (python 3.9) 安装了 geopandas。经过大量尝试和错误,我想出了这个 cx_freeze 安装脚本:

setup_script.py:

import os
from cx_Freeze import setup, Executable

# Dependencies are automatically detected, but it might need fine tuning.
PYTHON_INSTALL_DIR = r"C:\Users\YOUR_USERNAME\Miniconda3\envs\py39"
include_files = [(os.path.join(PYTHON_INSTALL_DIR, 'DLLs', 'tk86t.dll'), os.path.join('lib', 'tk86t.dll')),
                 (os.path.join(PYTHON_INSTALL_DIR, 'DLLs', 'tcl86t.dll'), os.path.join('lib', 'tcl86t.dll')),
                 (os.path.join(PYTHON_INSTALL_DIR, 'Library', 'bin', 'geos_c.dll'), os.path.join('lib', 'geos_c.dll')),
                 (os.path.join(PYTHON_INSTALL_DIR, 'Library', 'bin', 'spatialindex_c-64.dll'), os.path.join('lib', 'spatialindex_c-64.dll')),
                 (os.path.join(PYTHON_INSTALL_DIR, 'Library', 'bin', 'spatialindex-64.dll'), os.path.join('lib', 'spatialindex-64.dll')),
                 (os.path.join(PYTHON_INSTALL_DIR, 'Library', 'share','proj'), os.path.join('lib', 'proj')),
                 (os.path.join(PYTHON_INSTALL_DIR, 'Lib', 'site-packages','pygeos.libs'), os.path.join('lib', 'pygeos.libs'))
                 ]

build_exe_options = {'include_files':include_files, 
                    'bin_includes':[r"C:\Users\YOUR_USERNAME\Miniconda3\envs\py39\Library\bin\geos_c.dll",
                    r"C:\Users\YOUR_USERNAME\Miniconda3\envs\py39\Library\bin\spatialindex_c-64.dll",
                    r"C:\Users\YOUR_USERNAME\Miniconda3\envs\py39\Library\bin\spatialindex-64.dll"]}

# TARGET
target = Executable(
    script='geopandas_test.py',
    base='Win32GUI' # Tip: disable this line and try to debug your program with the command line first. You might see additional .dll import errors depending on your python installation
# to debug your .exe and remain the cmd output on your screen, you must start it from command line under windows.
)

# SETUP CX FREEZE
setup(
    name = "geopandas_exe_test",
    version = "0.0.1",
    description = "Geopandas on Win 10",
    options={"build_exe": build_exe_options},
    executables = [target]
)

并且在您的主脚本中,您应该包括这一行 os.environ['PROJ_LIB'] = './lib/proj'(这在 Win32GUI 模式下不起作用:pyproj.datadir.set_data_dir('./lib/proj')

这将是一个包含 tkinter 的完整工作示例:

geopandas_test.py:

import pandas as pd
import tkinter as tk

if (getattr(sys, "frozen", False)):
    print("Frozen State - Running as .exe")
    os.environ['PROJ_LIB'] = './lib/proj' # SET Proj4; alternative with datadir raises error while running as Win32GUI only mode: #datadir.set_data_dir('./lib/proj')
    
    import geopandas as geopd
    import pyproj
else:
    print("Running in dev mode...")
    import geopandas as geopd
    import pyproj


# Some sample Code below:
df = pd.DataFrame({'City': ['München'],'Latitude': [48],'Longitude': [11.5]})
gdf = geopd.GeoDataFrame(df, geometry=geopd.points_from_xy(df.Longitude, df.Latitude, crs="EPSG:4326"))
gdf = gdf.to_crs(25832)
print(gdf)

window = tk.Tk()
greeting = tk.Label(text=gdf)
greeting.pack()
window.mainloop()

为了完整起见。我按照以下步骤安装了 python 环境:

conda create --name py39 python=3.9
conda install geopandas
pip install --upgrade cx_Freeze
# DONT INSTALL tk ADDITIONALLY!
pip uninstall rtree # not sure if this is really neccessary or helps