如何在使用 matplotlib 的情况下使用 pyinstaller

Joh*_*ith 7 python matplotlib pyinstaller

我有这个脚本,我将一个 GUI 附加到它的前面,并希望将它分发给其他 DnD DM,以便他们用于将网格覆盖到图像上。唯一的问题是,每次我尝试使用 Pyinstaller 打包 python 脚本时,它都会抛出两个不同的错误。如果我运行pyinstaller --hidden-import matplotlib myscript.py它返回

    NameError: name 'defaultParams' is not defined
    [7532] Failed to execute script ImageGridder
Run Code Online (Sandbox Code Playgroud)

因此,我决定尝试使用该--onefile选项再次运行该命令。当我这样做时,它返回,

   RuntimeError: Could not find the matplotlib data files
   [18884] Failed to execute script ImageGridder
Run Code Online (Sandbox Code Playgroud)

现在,在这两个示例中,打包过程都完成了,所有文件似乎都已正确生成。只是当我运行它生成的 .exe 时,它​​崩溃了。我知道文件本身运行正常,因为我已经让它在我的台式机和笔记本电脑上正常运行和工作。我已经做了好几个小时的搜索,寻找任何有帮助的东西,但似乎没有任何效果。剧本本身,

from PIL import Image
import tkinter as tk
from tkinter import filedialog
import matplotlib.pyplot as PLT
import matplotlib.ticker as plticker

class gridder(tk.Tk):
    def __init__(self):
        tk.Tk.__init__(self)
        self.initialize()

    def initialize(self):        
        self.iWidth = tk.StringVar()
        self.iHeight = tk.StringVar()
        self.imgSelect = tk.StringVar()
        self.squareLength= tk.IntVar()
        self.ratioX=tk.IntVar()
        self.ratioY=tk.IntVar()
        self.checkSquare = tk.IntVar()
        self.colorLine= tk.StringVar()
        
        self.colorLine.set('k')
        self.checkSquare.set(0)
        self.ratioX.set(10)
        self.ratioY.set(10)
        self.squareLength.set(120)
        

        # row 1
        labelDisclaim = tk.Label(self, text='Currently only works with jpegs')
        labelDisclaim.grid(column=2, row=1)

        # row 2
        buttonOpen = tk.Button(self, text="Select an Image", command=self.openExplorer)
        buttonOpen.grid(column=1, row=2)

        labelSelected= tk.Label(self, text="Selected Image: ")
        labelSelected.grid(column=2,row=2)

        labelImgName = tk.Label(self, textvariable=self.imgSelect)
        labelImgName.grid(column=3,row=2)
        

        # row 3
        labelStaticImg= tk.Label(self, text="Width of image, in pixels: ")
        labelStaticImg.grid(column=1,row=3)

        labelImgWidth = tk.Label(self, textvariable=self.iWidth, anchor='w')
        labelImgWidth.grid(column=2,row=3)

        labelStaticHeight= tk.Label(self, text="Height of image, in pixels: ")
        labelStaticHeight.grid(column=3,row=3)

        labelImgHeight = tk.Label(self, textvariable=self.iHeight, anchor='w')
        labelImgHeight.grid(column=4,row=3)

        # row 4
        labelRatioX = tk.Label(self, text="Enter the Ratio along the X axis, default is 10: ")
        labelRatioX.grid(column=1,row=4)

        entryRatioX = tk.Entry(self, textvariable=self.ratioX)
        entryRatioX.grid(column=2,row=4)

        labelRatioY =tk.Label(self, text="Enter the Ratio along the Y axis, default is 10: ")
        labelRatioY.grid(column=3,row=4)

        entryRatioY = tk.Entry(self, textvariable=self.ratioY)
        entryRatioY.grid(column=4,row=4)

        # row 5
        labelSquare = tk.Label(self, text="For strict squares, in the sense of a battle map, check this ->")
        labelSquare.grid(column=1,row=5)

        checkboxSquare = tk.Checkbutton(self, variable=self.checkSquare, text="If checked, it will ignore the ratio and apply squares that are specified by the entry, (default 120x120) ->",wraplength=150)
        checkboxSquare.grid(column=2,row=5)

        labelSquareLength = tk.Label(self, text="Side length of Square: ")
        labelSquareLength.grid(column=3,row=5)

        entrySquareLength = tk.Entry(self, textvariable=self.squareLength)
        entrySquareLength.grid(column=4,row=5)

        
        # row 6
        labelColor= tk.Label(self, text="Enter a color for the grid, valid choices black=k, blue=b, green=g, red=r, white=w, brown=brown, yellow=yellow, cyan=c. Default is black: ",wraplength=250)
        labelColor.grid(column=1,row=6)

        entryColor = tk.Entry(self, textvariable=self.colorLine)
        entryColor.grid(column=2,row=6)
        
        execButton = tk.Button(self, text="Gridify", command=self.gridify)
        execButton.grid(column=4,row=6)
        
        # row 9
        button = tk.Button(self,text="Exit",command=self.closeProgram)
        button.grid(column=2,row=9)

        # row 10
        labelSig = tk.Label(self, text='By Johnathan Keith, 2020. Ver 1.0. This is free-to-use, and will always be. This was willingly distributed to the public.',wraplength=350)
        labelSig.grid(column=2,row=10)

        labelDisclaimer = tk.Label(self, text="This program does NOT generate pop up windows for bad data entries. If the image does not generate into the folder the script is in, you did something wrong.",wraplength=200)
        labelDisclaimer.grid(column=4,row=10)

    def openFile(self, imagefilename):
        Img = Image.open(imagefilename)
        height, width = Img.size
        self.iHeight.set(height)
        self.iWidth.set(width)

    def gridify(self):
        ratioX=0
        ratioY=0
        sidelengthy=0
        sidelengthx=0
        if self.checkSquare.get():
            ratioX=int(self.squareLength.get())
            ratioY=int(self.squareLength.get())
            sidelengthx=ratioX
            sidelengthy=ratioY
        else:
            ratioX=int(self.ratioX.get())
            ratioY=int(self.ratioY.get())
            sidelengthy=int(self.iWidth.get())/ratioY
            sidelengthx=int(self.iHeight.get())/ratioX
        image=Image.open(self.imgSelect.get())
        my_dpi=300.

        #set the figure up
        fig=PLT.figure(figsize=(float(image.size[0])/my_dpi,float(image.size[1])/my_dpi),dpi=my_dpi)
        ax=fig.add_subplot(111)

        #remove whitespace
        fig.subplots_adjust(left=0,right=1,bottom=0,top=1)

        #set gridding interval
        locx = plticker.MultipleLocator(base=sidelengthx)
        locy = plticker.MultipleLocator(base=sidelengthy)
        ax.xaxis.set_major_locator(locx)
        ax.yaxis.set_major_locator(locy)

        #add the grid
        ax.grid(which='major', axis='both', linestyle='-',color=self.colorLine.get())

        ax.imshow(image)

        token=self.imgSelect.get().split('/')
        saveName= "gridded_"+token[-1]
        
        # Save the figure
        fig.savefig(saveName,dpi=my_dpi)

    def closeProgram(self):
        self.destroy()
        exit()

    def dataEntry(self):
        if type(int) == type(int(bHeight)):
            self.bHeight = int(entryHeight.get())
        else:
            return
        
    def openExplorer(self):
        filename= filedialog.askopenfilename(initialdir="/", title="Select an Image", filetypes=(("jpeg files", "*.jpg"),("all files", "*.*")))
        if filename:
           self.imgSelect.set(filename)
           self.openFile(filename)
           

if __name__ == "__main__":
    app = gridder()
    app.title('Image Gridder')
    app.mainloop()

Run Code Online (Sandbox Code Playgroud)

我正在运行 python 3.8、matplotlib 3.3.0、tkinter、PIL 6.2.2 和 pyinstaller 3.6。

使用--onefile命令时警告文件的内容:


This file lists modules PyInstaller was not able to find. This does not
necessarily mean this module is required for running you program. Python and
Python 3rd-party packages include a lot of conditional or optional modules. For
example the module 'ntpath' only exists on Windows, whereas the module
'posixpath' only exists on Posix systems.

Types if import:
* top-level: imported at the top-level - look at these first
* conditional: imported within an if-statement
* delayed: imported from within a function
* optional: imported within a try-except-statement

IMPORTANT: Do NOT post this list to the issue-tracker. Use it as a basis for
           yourself tracking down the missing module. Thanks!

missing module named _posixsubprocess - imported by subprocess (optional), multiprocessing.util (delayed)
missing module named 'org.python' - imported by copy (optional), xml.sax (delayed, conditional), setuptools.sandbox (conditional)
missing module named _frozen_importlib_external - imported by importlib._bootstrap (delayed), importlib (optional), importlib.abc (optional), zipimport (top-level)
excluded module named _frozen_importlib - imported by importlib (optional), importlib.abc (optional), zipimport (top-level), PyInstaller.loader.pyimod02_archive (delayed, conditional)
missing module named urllib.pathname2url - imported by urllib (conditional), PyInstaller.lib.modulegraph._compat (conditional)
missing module named _posixshmem - imported by multiprocessing.resource_tracker (conditional), multiprocessing.shared_memory (conditional)
missing module named multiprocessing.set_start_method - imported by multiprocessing (top-level), multiprocessing.spawn (top-level)
missing module named multiprocessing.get_start_method - imported by multiprocessing (top-level), multiprocessing.spawn (top-level)
missing module named _scproxy - imported by urllib.request (conditional)
missing module named termios - imported by tty (top-level), getpass (optional)
missing module named resource - imported by posix (top-level), test.support (optional)
missing module named 'java.lang' - imported by platform (delayed, optional), xml.sax._exceptions (conditional)
missing module named vms_lib - imported by platform (delayed, conditional, optional)
missing module named java - imported by platform (delayed)
missing module named _winreg - imported by platform (delayed, optional), numpy.distutils.cpuinfo (delayed, conditional, optional), pkg_resources._vendor.appdirs (delayed, conditional)
missing module named multiprocessing.get_context - imported by multiprocessing (top-level), multiprocessing.pool (top-level), multiprocessing.managers (top-level), multiprocessing.sharedctypes (top-level)
missing module named multiprocessing.TimeoutError - imported by multiprocessing (top-level), multiprocessing.pool (top-level)
missing module named multiprocessing.BufferTooShort - imported by multiprocessing (top-level), multiprocessing.connection (top-level)
missing module named multiprocessing.AuthenticationError - imported by multiprocessing (top-level), multiprocessing.connection (top-level)
missing module named asyncio.DefaultEventLoopPolicy - imported by asyncio (delayed, conditional), asyncio.events (delayed, conditional)
missing module named readline - imported by cmd (delayed, conditional, optional), code (delayed, conditional, optional), pdb (delayed, optional)
missing module named org - imported by pickle (optional)
missing module named grp - imported by shutil (optional), tarfile (optional), pathlib (delayed), distutils.archive_util (optional)
missing module named pwd - imported by posixpath (delayed, conditional), shutil (optional), tarfile (optional), pathlib (delayed, conditional, optional), http.server (delayed, optional), webbrowser (delayed), netrc (delayed, conditional), getpass (delayed), distutils.util (delayed, conditional, optional), distutils.archive_util (optional)
missing module named posix - imported by os (conditional, optional), shutil (conditional)
missing module named 'multiprocessing.forking' - imported by C:\Users\Owner\AppData\Local\Programs\Python\Python38-32\Lib\site-packages\PyInstaller\loader\rthooks\pyi_rth_multiprocessing.py (optional)
missing module named 'win32com.gen_py' - imported by win32com (conditional, optional), C:\Users\Owner\AppData\Local\Programs\Python\Python38-32\Lib\site-packages\PyInstaller\loader\rthooks\pyi_rth_win32comgenpy.py (top-level)
missing module named pyimod03_importers - imported by PyInstaller.loader.pyimod02_archive (delayed, conditional), C:\Users\Owner\AppData\Local\Programs\Python\Python38-32\Lib\site-packages\PyInstaller\loader\rthooks\pyi_rth_pkgres.py (top-level)
missing module named 'pkg_resources.extern.pyparsing' - imported by pkg_resources._vendor.packaging.requirements (top-level), pkg_resources._vendor.packaging.markers (top-level)
missing module named _uuid - imported by uuid (optional)
missing module named __builtin__ - imported by PIL.Image (optional), numpy.core.numerictypes (conditional), numpy.core.numeric (conditional), numpy.lib.function_base (conditional), numpy.lib._iotools (conditional), numpy.ma.core (conditional), numpy.distutils.misc_util (delayed, conditional), numpy (conditional), pyparsing (conditional), pkg_resources._vendor.pyparsing (conditional), setuptools._vendor.pyparsing (conditional)
missing module named ordereddict - imported by pyparsing (optional), pkg_resources._vendor.pyparsing (optional), setuptools._vendor.pyparsing (optional)
missing module named StringIO - imported by PyInstaller.lib.modulegraph._compat (conditional), PyInstaller.lib.modulegraph.zipio (conditional), setuptools._vendor.six (conditional), numpy.lib.utils (delayed, conditional), numpy.lib.format (delayed, conditional), numpy.testing._private.utils (conditional), six (conditional), pkg_resources._vendor.six (conditional)
missing module named 'com.sun' - imported by pkg_resources._vendor.appdirs (delayed, conditional, optional)
missing module named com - imported by pkg_resources._vendor.appdirs (delayed)
missing module named pkg_resources.extern.packaging - imported by pkg_resources.extern (top-level), pkg_resources (top-level)
missing module named pkg_resources.extern.appdirs - imported by pkg_resources.extern (top-level), pkg_resources (top-level)
missing module named 'pkg_resources.extern.six.moves' - imported by pkg_resources (top-level), pkg_resources._vendor.packaging.requirements (top-level)
missing module named pkg_resources.extern.six - imported by pkg_resources.extern (top-level), pkg_resources (top-level), pkg_resources.py31compat (top-level)
missing module named pytest - imported by numpy._pytesttester (delayed), matplotlib (delayed, optional)
missing module named commands - imported by numpy.distutils.cpuinfo (conditional)
missing module named setuptools.extern.packaging - imported by setuptools.extern (top-level), setuptools.dist (top-level), setuptools.command.egg_info (top-level)
missing module named 'setuptools.extern.six' - imported by setuptools (top-level), setuptools.extension (top-level)
missing module named 'setuptools.extern.packaging.version' - imported by setuptools.config (top-level), setuptools.msvc (top-level)
missing module named setuptools.extern.six.moves.filterfalse - imported by setuptools.extern.six.moves (top-level), setuptools.dist (top-level), setuptools.msvc (top-level)
missing module named setuptools.extern.six.moves.filter - imported by setuptools.extern.six.moves (top-level), setuptools.dist (top-level), setuptools.ssl_support (top-level), setuptools.command.py36compat (top-level)
missing module named _manylinux - imported by setuptools.pep425tags (delayed, optional)
missing module named 'setuptools.extern.packaging.utils' - imported by setuptools.wheel (top-level)
missing module named wincertstore - imported by setuptools.ssl_support (delayed, optional)
missing module named 'backports.ssl_match_hostname' - imported by setuptools.ssl_support (optional)
missing module named backports - imported by setuptools.ssl_support (optional)
missing module named 'setuptools._vendor.six.moves' - imported by 'setuptools._vendor.six.moves' (top-level)
missing module named 'setuptools.extern.pyparsing' - imported by setuptools._vendor.packaging.markers (top-level), setuptools._vendor.packaging.requirements (top-level)
missing module named setuptools.extern.six.moves.map - imported by setuptools.extern.six.moves (top-level), setuptools.dist (top-level), setuptools.command.easy_install (top-level), setuptools.sandbox (top-level), setuptools.package_index (top-level), setuptools.ssl_support (top-level), setuptools.command.egg_info (top-level), setuptools.namespaces (top-level)
runtime module named setuptools.extern.six.moves - imported by setuptools.dist (top-level), setuptools.py33compat (top-level), configparser (top-level), setuptools.command.easy_install (top-level), setuptools.sandbox (top-level), setuptools.command.setopt (top-level), setuptools.package_index (top-level), setuptools.ssl_support (top-level), setuptools.command.egg_info (top-level), setuptools.command.py36compat (top-level), setuptools.namespaces (top-level), setuptools.msvc (top-level), 'setuptools._vendor.six.moves' (top-level)
missing module named setuptools.extern.six - imported by setuptools.extern (top-level), setuptools.monkey (top-level), setuptools.dist (top-level), setuptools.extern.six.moves (top-level), setuptools.py33compat (top-level), setuptools.config (top-level), setuptools.command.easy_install (top-level), setuptools.sandbox (top-level), setuptools.py27compat (top-level), setuptools.package_index (top-level), setuptools.wheel (top-level), setuptools.pep425tags (top-level), setuptools.command.egg_info (top-level), setuptools.command.sdist (top-level), setuptools.command.bdist_egg (top-level), setuptools.unicode_utils (top-level), setuptools.command.develop (top-level)
missing module named 'numpy_distutils.cpuinfo' - imported by numpy.f2py.diagnose (delayed, conditional, optional)
missing module named 'numpy_distutils.fcompiler' - imported by numpy.f2py.diagnose (delayed, conditional, optional)
missing module named 'numpy_distutils.command' - imported by numpy.f2py.diagnose (delayed, conditional, optional)
missing module named numpy_distutils - imported by numpy.f2py.diagnose (delayed, optional)
missing module named __svn_version__ - imported by numpy.f2py.__version__ (optional)
missing module named numarray - imported by numpy.distutils.system_info (delayed, conditional, optional)
missing module named Numeric - imported by numpy.distutils.system_info (delayed, conditional, optional)
missing module named ConfigParser - imported by numpy.distutils.system_info (conditional), numpy.distutils.npy_pkg_config (conditional)
missing module named _curses - imported by curses (top-level), curses.has_key (top-level)
missing module named _dummy_threading - imported by dummy_threading (optional)
missing module named 'nose.plugins' - imported by numpy.testing._private.noseclasses (top-level), numpy.testing._private.nosetester (delayed)
missing module named scipy - imported by numpy.testing._private.nosetester (delayed, conditional)
missing module named 'nose.util' - imported by numpy.testing._private.noseclasses (top-level)
missing module named nose - imported by numpy.testing._private.utils (delayed, optional), numpy.testing._private.decorators (delayed), numpy.testing._private.noseclasses (top-level)
missing module named dummy_thread - imported by numpy.core.arrayprint (conditional, optional)
missing module named thread - imported by numpy.core.arrayprint (conditional, optional), PyInstaller.loader.pyimod02_archive (conditional)
missing module named cPickle - imported by numpy.core.numeric (conditional)
missing module named cStringIO - imported by cPickle (top-level)
missing module named copy_reg - imported by cPickle (top-level), cStringIO (top-level), numpy.core (conditional)
missing module named pickle5 - imported by numpy.core.numeric (conditional, optional)
missing module named numpy.core.number - imported by numpy.core (delayed), numpy.testing._private.utils (delayed)
missing module named numpy.core.signbit - imported by numpy.core (delayed), numpy.testing._private.utils (delayed)
missing module named numpy.core.float64 - imported by numpy.core (delayed), numpy.testing._private.utils (delayed)
missing module named numpy.core.float32 - imported by numpy.core (top-level), numpy.testing._private.utils (top-level)
missing module named numpy.lib.i0 - imported by numpy.lib (top-level), numpy.dual (top-level)
missing module named numpy.core.integer - imported by numpy.core (top-level), numpy.fft.helper (top-level)
missing module named numpy.core.sqrt - imported by numpy.core (top-level), numpy.linalg.linalg (top-level), numpy.fft.fftpack (top-level)
missing module named numpy.core.conjugate - imported by numpy.core (top-level), numpy.fft.fftpack (top-level)
missing module named numpy.core.divide - imported by numpy.core (

小智 8

您可以尝试通过安装旧版本的 matplotlib 包来解决此问题。例如:

pip install matplotlib==3.2.2
Run Code Online (Sandbox Code Playgroud)

  • 事实证明,在 matplotlib 3.3 中,有一个环境变量被删除并导致 exe 崩溃。“MATPLOTLIBDATA 环境变量在 Matplotlib 3.1 中已弃用,并将在 3.3 中删除。”降级到 3.2.2 显然是我的问题。我还将pyinstaller升级到4.0.dev (2认同)

小智 6

--onefile模式下,基于 PyInstaller 贡献者的这个提交,它引用了https://github.com/pyinstaller/pyinstaller/issues/5004,你可以修改PyInstaller\hooks\hook-matplotlib.py它:

datas = [
    (mpl_data_dir, "matplotlib/mpl-data"),
]
Run Code Online (Sandbox Code Playgroud)

代替

datas = [   datas = [
    (mpl_data_dir, "mpl-data"),
]
Run Code Online (Sandbox Code Playgroud)