py2exe 和 numpy 相处不好

发布于 2024-10-16 05:39:44 字数 8392 浏览 2 评论 0 原文

我正在尝试使用 py2exe-0.6.9.win32 来包装我用 Python2.6.5 编写的应用程序,使用以下对象库和关联的下载文件名:

matplotlib-0.99.3.win32

numpy-1.4.1-win32

scipy-0.8.0b1-win32

wxPython2.8-win32-unicode -2.8.11.0

当我尝试启动生成的 .exe 文件时收到错误消息。目前,错误消息与 numpy 相关,尽管在此之前我收到了与 matplot lib 数据文件未加载相关的信息,从而阻止了 exe 文件的启动。

我没有发布一英里的代码和所有错误消息,而是发布了一个更普遍的问题:任何人都可以向我展示一些使用 py2exe 创建工作 exe 文件使所有这些对象库和版本能够很好地协同工作的说明?

我一直在阅读有关该主题的谷歌搜索的内容,但这似乎是一场徒劳的追逐,因为每个人都在使用不同版本的不同内容。如果有影响的话,我可以更改其中一些对象库的某些版本,但我已经在此信号处理应用程序中编写了 5,000 行代码,并且我不希望必须重新编写所有代码,如果可能的。


编辑:

这是我的代码的简化版本,位于名为 GUIdiagnostics.py 的文件中,我制作该文件是为了测试 py2exe 脚本导入实际应用程序中所需的所有库的能力:

import time
import wxversion
import wx
import csv
import os
import pylab as p
from scipy import stats
import math
from matplotlib import *
from numpy import *
from pylab import *
import scipy.signal as signal
import scipy.optimize
import Tkinter

ID_EXIT = 130

class MainWindow(wx.Frame):
    def __init__(self, parent,id,title):
        wx.Frame.__init__(self,parent,wx.ID_ANY,title, size = (500,500), style =     wx.DEFAULT_FRAME_STYLE | wx.NO_FULL_REPAINT_ON_RESIZE)

        # A button
        self.button =wx.Button(self, label="Click Here", pos=(160, 120))
        self.Bind(wx.EVT_BUTTON,self.OnClick,self.button)

        # the combobox Control
        self.sampleList = ['first','second','third']
        self.lblhear = wx.StaticText(self, label="Choose TestID to filter:", pos=(20, 75))
        self.edithear = wx.ComboBox(self, pos=(160, 75), size=(95, -1),     choices=self.sampleList, style=wx.CB_DROPDOWN)

        # the progress bar
        self.progressMax = 3
        self.count = 0
        self.newStep='step '+str(self.count)
        self.dialog = None

        #-------Setting up the menu.
        # create a new instance of the wx.Menu() object
        filemenu = wx.Menu()

        # enables user to exit the program gracefully
        filemenu.Append(ID_EXIT, "E&xit", "Terminate the program")

        #------- Creating the menu.
        # create a new instance of the wx.MenuBar() object
        menubar = wx.MenuBar()
        # add our filemenu as the first thing on this menu bar
        menubar.Append(filemenu,"&File")
        # set the menubar we just created as the MenuBar for this frame
        self.SetMenuBar(menubar)
        #----- Setting menu event handler
        wx.EVT_MENU(self,ID_EXIT,self.OnExit)

        self.Show(True)

    def OnExit(self,event):
        self.Close(True)

    def OnClick(self,event):
        try:
            if not self.dialog:
                self.dialog = wx.ProgressDialog("Progress in processing your data.", self.newStep,
                                            self.progressMax,
                                            style=wx.PD_CAN_ABORT
                                            | wx.PD_APP_MODAL
                                            | wx.PD_SMOOTH)
            self.count += 1
            self.newStep='Start'
            (keepGoing, skip) = self.dialog.Update(self.count,self.newStep)
            TestID = self.edithear.GetValue()

            self.count += 1
            self.newStep='Continue.'
            (keepGoing, skip) = self.dialog.Update(self.count,self.newStep)
            myObject=myClass(TestID)
            print myObject.description

            self.count += 1
            self.newStep='Finished.'
            (keepGoing, skip) = self.dialog.Update(self.count,self.newStep)

            self.count = 0

            self.dialog.Destroy()

        except:
            self.dialog.Destroy()
            import sys, traceback
            xc = traceback.format_exception(*sys.exc_info())
            d = wx.MessageDialog( self, ''.join(xc),"Error",wx.OK)
            d.ShowModal() # Show it
            d.Destroy() #finally destroy it when finished

class myClass():
    def __init__(self,TestID):
        self.description = 'The variable name is:  '+str(TestID)+'. '

app = wx.PySimpleApp()
frame = MainWindow(None,-1,"My GUI")
app.MainLoop()

这里是setup.py 的代码,它是包含我的 py2exe 代码的文件:

from distutils.core import setup
import py2exe

# Remove the build folder, a bit slower but ensures that build contains the latest
import shutil
shutil.rmtree("build", ignore_errors=True)

# my setup.py is based on one generated with gui2exe, so data_files is done a bit differently
data_files = []
includes = []
excludes = ['_gtkagg', '_tkagg', 'bsddb', 'curses', 'pywin.debugger',
        'pywin.debugger.dbgcon', 'pywin.dialogs', 'tcl',
        'Tkconstants', 'Tkinter', 'pydoc', 'doctest', 'test', 'sqlite3'
        ]
packages = ['pytz']
dll_excludes = ['libgdk-win32-2.0-0.dll', 'libgobject-2.0-0.dll', 'tcl84.dll',
            'tk84.dll']
icon_resources = []
bitmap_resources = []
other_resources = []

# add the mpl mpl-data folder and rc file
import matplotlib as mpl
data_files += mpl.get_py2exe_datafiles()

setup(
    windows=['GUIdiagnostics.py'],
                      # compressed and optimize reduce the size
    options = {"py2exe": {"compressed": 2, 
                      "optimize": 2,
                      "includes": includes,
                      "excludes": excludes,
                      "packages": packages,
                      "dll_excludes": dll_excludes,
                      # using 2 to reduce number of files in dist folder
                      # using 1 is not recommended as it often does not work
                      "bundle_files": 2,
                      "dist_dir": 'dist',
                      "xref": False,
                      "skip_archive": False,
                      "ascii": False,
                      "custom_boot_script": '',
                     }
          },

    # using zipfile to reduce number of files in dist
    zipfile = r'lib\library.zip',

    data_files=data_files
)

我通过按照以下链接在 Windows 命令行界面 (cmd.exe) 中键入以下行来运行此代码:

setup.py py2exe

Py2exe 然后运行,但是当我尝试启动生成的 exe 文件,它会创建一个包含以下消息的日志文件:

Traceback (most recent call last):
  File "setup.py", line 6, in <module>
  File "zipextimporter.pyo", line 82, in load_module
  File "pylab.pyo", line 1, in <module>
  File "zipextimporter.pyo", line 82, in load_module
  File "matplotlib\pylab.pyo", line 206, in <module>
  File "zipextimporter.pyo", line 82, in load_module
  File "matplotlib\mpl.pyo", line 3, in <module>
  File "zipextimporter.pyo", line 82, in load_module
  File "matplotlib\axes.pyo", line 14, in <module>
  File "zipextimporter.pyo", line 82, in load_module
  File "matplotlib\collections.pyo", line 21, in <module>
  File "zipextimporter.pyo", line 82, in load_module
  File "matplotlib\backend_bases.pyo", line 32, in <module>
  File "zipextimporter.pyo", line 82, in load_module
  File "matplotlib\widgets.pyo", line 12, in <module>
  File "zipextimporter.pyo", line 82, in load_module
  File "matplotlib\mlab.pyo", line 388, in <module>
TypeError: unsupported operand type(s) for %: 'NoneType' and 'dict'

有人可以告诉我如何编辑 setup.py 以便 py2exe 可以创建运行 numpy、scipy、matplotlib 等的可用可执行文件吗?< /strong>


第二次编辑:

好的。我今天再次尝试了 RC 的建议,现在我对此有了新的想法,并且我得到了相同的错误,但我将其包含在下面。以下是我按照模板创建的 cxsetup.py 文件的代码: http:// cx-freeze.sourceforge.net/cx_Freeze.html

from cx_Freeze import setup, Executable

setup(
        name = "Potark",
        version = "0.1",
        description = "My application.",
        executables = [Executable("Potark-ICG.py")])

不幸的是,使用以下命令在命令行( cmd.exe )中运行它:

python cxsetup.py build

会在命令行中生成以下错误:

ImportError: No module named cx_Freeze

命令行中的目录是我的应用程序的目录,该目录位于桌面的子文件夹中。这与 python 应用程序的目录不同,但我认为 cmd.exe 可以解决这个问题,因为 python 可以解决它。 我错了吗?作为测试,我将以下代码行添加到 cxsetup.py 的第一行:

import matplotlib

但这生成了几乎相同的错误:

ImportError: No module named matplotlib

我试图保持该线程的重点和简短,但它变得有点长了。 任何人都可以帮我解决这个问题吗?我不想做所有切换到 cx_freeze 的工作,却发现它无法与 numpy、matplotlib、scipy 等一起使用。

I am trying to use py2exe-0.6.9.win32 to wrap up an application that I have written in Python2.6.5 using the following object libraries with associated download file names:

matplotlib-0.99.3.win32

numpy-1.4.1-win32

scipy-0.8.0b1-win32

wxPython2.8-win32-unicode-2.8.11.0

I am getting error messages when I try to launch the resulting .exe file. At the moment, the error message is related to numpy, though before that I was getting something related to matplot lib data files not loading and thus blocking the launch of my exe file.

Rather than post a mile of code and all the error messages, I am posting a more general question: Can anyone show me some instructions for making all of these object libraries and versions play well together using py2exe to create a working exe file?

I have been reading things that come up with google searches on the topic, but it seems like a wild goose chase in that everyone is using different versions of different things. I can change some of the versions of some of these object libraries if that makes a difference, but I have already written 5,000 lines of code in this signal processing application, and I would prefer not to have to re-write all of it, if possible.


EDIT:

Here is a simplified version of my code in a file called GUIdiagnostics.py that I made to test the ability of my py2exe script to import all the libraries that I need in my real application:

import time
import wxversion
import wx
import csv
import os
import pylab as p
from scipy import stats
import math
from matplotlib import *
from numpy import *
from pylab import *
import scipy.signal as signal
import scipy.optimize
import Tkinter

ID_EXIT = 130

class MainWindow(wx.Frame):
    def __init__(self, parent,id,title):
        wx.Frame.__init__(self,parent,wx.ID_ANY,title, size = (500,500), style =     wx.DEFAULT_FRAME_STYLE | wx.NO_FULL_REPAINT_ON_RESIZE)

        # A button
        self.button =wx.Button(self, label="Click Here", pos=(160, 120))
        self.Bind(wx.EVT_BUTTON,self.OnClick,self.button)

        # the combobox Control
        self.sampleList = ['first','second','third']
        self.lblhear = wx.StaticText(self, label="Choose TestID to filter:", pos=(20, 75))
        self.edithear = wx.ComboBox(self, pos=(160, 75), size=(95, -1),     choices=self.sampleList, style=wx.CB_DROPDOWN)

        # the progress bar
        self.progressMax = 3
        self.count = 0
        self.newStep='step '+str(self.count)
        self.dialog = None

        #-------Setting up the menu.
        # create a new instance of the wx.Menu() object
        filemenu = wx.Menu()

        # enables user to exit the program gracefully
        filemenu.Append(ID_EXIT, "E&xit", "Terminate the program")

        #------- Creating the menu.
        # create a new instance of the wx.MenuBar() object
        menubar = wx.MenuBar()
        # add our filemenu as the first thing on this menu bar
        menubar.Append(filemenu,"&File")
        # set the menubar we just created as the MenuBar for this frame
        self.SetMenuBar(menubar)
        #----- Setting menu event handler
        wx.EVT_MENU(self,ID_EXIT,self.OnExit)

        self.Show(True)

    def OnExit(self,event):
        self.Close(True)

    def OnClick(self,event):
        try:
            if not self.dialog:
                self.dialog = wx.ProgressDialog("Progress in processing your data.", self.newStep,
                                            self.progressMax,
                                            style=wx.PD_CAN_ABORT
                                            | wx.PD_APP_MODAL
                                            | wx.PD_SMOOTH)
            self.count += 1
            self.newStep='Start'
            (keepGoing, skip) = self.dialog.Update(self.count,self.newStep)
            TestID = self.edithear.GetValue()

            self.count += 1
            self.newStep='Continue.'
            (keepGoing, skip) = self.dialog.Update(self.count,self.newStep)
            myObject=myClass(TestID)
            print myObject.description

            self.count += 1
            self.newStep='Finished.'
            (keepGoing, skip) = self.dialog.Update(self.count,self.newStep)

            self.count = 0

            self.dialog.Destroy()

        except:
            self.dialog.Destroy()
            import sys, traceback
            xc = traceback.format_exception(*sys.exc_info())
            d = wx.MessageDialog( self, ''.join(xc),"Error",wx.OK)
            d.ShowModal() # Show it
            d.Destroy() #finally destroy it when finished

class myClass():
    def __init__(self,TestID):
        self.description = 'The variable name is:  '+str(TestID)+'. '

app = wx.PySimpleApp()
frame = MainWindow(None,-1,"My GUI")
app.MainLoop()

Here is the code for setup.py, which is the file containing my py2exe code:

from distutils.core import setup
import py2exe

# Remove the build folder, a bit slower but ensures that build contains the latest
import shutil
shutil.rmtree("build", ignore_errors=True)

# my setup.py is based on one generated with gui2exe, so data_files is done a bit differently
data_files = []
includes = []
excludes = ['_gtkagg', '_tkagg', 'bsddb', 'curses', 'pywin.debugger',
        'pywin.debugger.dbgcon', 'pywin.dialogs', 'tcl',
        'Tkconstants', 'Tkinter', 'pydoc', 'doctest', 'test', 'sqlite3'
        ]
packages = ['pytz']
dll_excludes = ['libgdk-win32-2.0-0.dll', 'libgobject-2.0-0.dll', 'tcl84.dll',
            'tk84.dll']
icon_resources = []
bitmap_resources = []
other_resources = []

# add the mpl mpl-data folder and rc file
import matplotlib as mpl
data_files += mpl.get_py2exe_datafiles()

setup(
    windows=['GUIdiagnostics.py'],
                      # compressed and optimize reduce the size
    options = {"py2exe": {"compressed": 2, 
                      "optimize": 2,
                      "includes": includes,
                      "excludes": excludes,
                      "packages": packages,
                      "dll_excludes": dll_excludes,
                      # using 2 to reduce number of files in dist folder
                      # using 1 is not recommended as it often does not work
                      "bundle_files": 2,
                      "dist_dir": 'dist',
                      "xref": False,
                      "skip_archive": False,
                      "ascii": False,
                      "custom_boot_script": '',
                     }
          },

    # using zipfile to reduce number of files in dist
    zipfile = r'lib\library.zip',

    data_files=data_files
)

I run this code by typing the following line into the command line interface of windows (cmd.exe) as per the following link:

setup.py py2exe

Py2exe then runs, but when I try to launch the resulting exe file, it creates a log file containing the following message:

Traceback (most recent call last):
  File "setup.py", line 6, in <module>
  File "zipextimporter.pyo", line 82, in load_module
  File "pylab.pyo", line 1, in <module>
  File "zipextimporter.pyo", line 82, in load_module
  File "matplotlib\pylab.pyo", line 206, in <module>
  File "zipextimporter.pyo", line 82, in load_module
  File "matplotlib\mpl.pyo", line 3, in <module>
  File "zipextimporter.pyo", line 82, in load_module
  File "matplotlib\axes.pyo", line 14, in <module>
  File "zipextimporter.pyo", line 82, in load_module
  File "matplotlib\collections.pyo", line 21, in <module>
  File "zipextimporter.pyo", line 82, in load_module
  File "matplotlib\backend_bases.pyo", line 32, in <module>
  File "zipextimporter.pyo", line 82, in load_module
  File "matplotlib\widgets.pyo", line 12, in <module>
  File "zipextimporter.pyo", line 82, in load_module
  File "matplotlib\mlab.pyo", line 388, in <module>
TypeError: unsupported operand type(s) for %: 'NoneType' and 'dict'

Can anyone show me how to edit setup.py so that py2exe can create a usable executable running numpy, scipy, matplotlib, etc.?


SECOND EDIT:

OK. I tried RC's advice again today now that I have a fresh mind for this, and I got the same errorr, but I am including it below. Here is the code for a file called cxsetup.py that I created following the template at: http://cx-freeze.sourceforge.net/cx_Freeze.html .

from cx_Freeze import setup, Executable

setup(
        name = "Potark",
        version = "0.1",
        description = "My application.",
        executables = [Executable("Potark-ICG.py")])

Unfortunately, running it in the command line ( cmd.exe ) with the command:

python cxsetup.py build

generates the following error in the command line:

ImportError: No module named cx_Freeze

The directory in the command line is the directory for my application, which is in a subfolder of the desktop. That is different than the directory for the python application, but I assume cmd.exe can figure that out because python can figure it out. Am I wrong? As a test, I added the following line of code to the first line of cxsetup.py :

import matplotlib

But that generated the almost identical error:

ImportError: No module named matplotlib

I have tried to keep this thread focused and short, but it is getting kind of long. Can anyone help me with this? I would hate to do all the work of switching to cx_freeze only to find that it cannot work with numpy, matplotlib, scipy, etc.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

风苍溪 2024-10-23 05:39:44

似乎底部提到的问题: http://www.py2exe.org/index.html cgi/MatPlotLib

看起来您需要对 mlab.py 进行一些小更改:

psd.__doc__ = psd.__doc__ % kwdocd

如果

if psd.__doc__ is not None:
    psd.__doc__ = psd.__doc__ % kwdocd
else:
    psd.__doc__ = ""

您还没有看到此页面,这就是我到达那里的方式:http://www.py2exe.org/index.cgi/WorkingWithVariousPackagesAndModules

Seems like the problem mentioned on the bottom of this: http://www.py2exe.org/index.cgi/MatPlotLib

Looks like you need to make a few small changes to mlab.py:

psd.__doc__ = psd.__doc__ % kwdocd

to

if psd.__doc__ is not None:
    psd.__doc__ = psd.__doc__ % kwdocd
else:
    psd.__doc__ = ""

If you haven't seen this page already this is how I got there: http://www.py2exe.org/index.cgi/WorkingWithVariousPackagesAndModules

牵你的手,一向走下去 2024-10-23 05:39:44

正如其他人提到的,py2exe 似乎需要根据具体情况进行丑陋的随机修复......似乎没有办法解决它。此外,有些错误不会消失,并且不会影响程序,但会导致程序通知用户退出后创建了错误日志。为了避免这种情况,我使用以下代码:

import sys
IS_USING_PY2EXE = hasattr(sys, "frozen")

# Redirect output to a file if this program is compiled.     
if IS_USING_PY2EXE:
    # Redirect log to a file.
    LOG_FILENAME = os.path.join(logDir, "myfile.log")
    print('Redirecting Stderr... to %s' % LOG_FILENAME)
    logFile = open(os.path.join(LOG_FILENAME),"w") # a --> append, "w" --> write

    sys.stderr = logFile
    sys.stdout = logFile

As others have mentioned, py2exe seems to require ugly, random fixes on a case-by-case basis... there appears to be no way around it. Also, some errors refuse to go away, and do not impact the program, but do cause the program to inform the user that an errors log was created after exit. To avoid that, I use this code:

import sys
IS_USING_PY2EXE = hasattr(sys, "frozen")

# Redirect output to a file if this program is compiled.     
if IS_USING_PY2EXE:
    # Redirect log to a file.
    LOG_FILENAME = os.path.join(logDir, "myfile.log")
    print('Redirecting Stderr... to %s' % LOG_FILENAME)
    logFile = open(os.path.join(LOG_FILENAME),"w") # a --> append, "w" --> write

    sys.stderr = logFile
    sys.stdout = logFile
风筝有风,海豚有海 2024-10-23 05:39:44

这可能只是我很愚蠢,但是你为什么不尝试将你的 scipy 从 0.8.0b1 更新到 0.8.0 并用 matplotlib 做同样的事情呢? Numpy 1.4.1 应该还可以。

This might just me being stupid, but why dont you try to update your scipy from 0.8.0b1 to 0.8.0 and do the same with matplotlib? Numpy 1.4.1 should still be fine.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文