py2exe и numpy не ладят

Я пытаюсь использовать py2exe-0.6.9.win32 для завершения приложения, которое я написал на Python2.6.5, используя следующие библиотеки объектов с соответствующими именами загружаемых файлов:

матплотлиб-0.99.3.win32

numpy-1.4.1-win32

scipy-0.8.0b1-win32

wxPython2.8-win32-юникод-2.8.11.0

Я получаю сообщения об ошибках, когда пытаюсь запустить полученный файл .exe. На данный момент сообщение об ошибке связано с numpy, хотя до этого я получал что-то, связанное с тем, что файлы данных matplot lib не загружались и, таким образом, блокировали запуск моего исполняемого файла.

Вместо того, чтобы публиковать километр кода и все сообщения об ошибках, я публикую более общий вопрос: Может ли кто-нибудь показать мне некоторые инструкции, как заставить все эти библиотеки объектов и версии хорошо работать вместе, используя py2exe для создания рабочего exe-файла. ?

Я читал вещи, которые появляются при поиске в Google по этой теме, но это похоже на погоню за дикими гусями, поскольку все используют разные версии разных вещей. Я могу изменить некоторые версии некоторых из этих библиотек объектов, если это имеет значение, но я уже написал 5000 строк кода в этом приложении для обработки сигналов, и я бы предпочел не переписывать его полностью, если возможно.


ИЗМЕНИТЬ:

Вот упрощенная версия моего кода в файле с именем 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, но когда я пытаюсь запустить полученный исполняемый файл, он создает файл журнала, содержащий следующее сообщение:

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 и т. д.?


ВТОРОЕ ИЗМЕНЕНИЕ:

OK. Я снова попробовал совет 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 и т. д.


person MedicalMath    schedule 04.02.2011    source источник
comment
возможно, вы могли бы попробовать cxfreeze и посмотреть, поможет ли это создать работающий exe   -  person    schedule 04.02.2011
comment
Спасибо. Я пробовал это, но я получаю другое сообщение об ошибке от cxfreeze, и я бы предпочел сосредоточить внимание на этой ветке, чтобы не сбивать людей с толку слишком большим количеством кода или слишком большим количеством сообщений об ошибках. Этот аспект программирования для меня нов.   -  person MedicalMath    schedule 04.02.2011
comment
Ничего страшного, просто стоило попробовать.   -  person    schedule 04.02.2011
comment
Сегодня я снова попробовал ваш совет и получил сообщение об ошибке, описанное во втором моем редактировании выше. Я был бы очень признателен за некоторые советы.   -  person MedicalMath    schedule 04.02.2011
comment
Я не хочу никого смущать переходом на cx_freeze. Я так же счастлив сделать это в py2exe. Мне просто нужно что-то, что работает с numpy, scipy, matplotlib и т. д., как описано выше. У меня такое чувство, что это может стать волосатым, если кто-то не предложит простое решение. И я боюсь, что с cx_freeze будет так же грязно, как и с py2exe. Если только кто-то, кто знает и проводит с этим немного времени, может дать прямое резюме решения. ВСЕ мой соответствующий код выше.   -  person MedicalMath    schedule 04.02.2011
comment
Вы пробовали с bundle_files: 3 ? Сообщение об ошибке заставляет меня думать, что проблема связана с пакетированием, поэтому попытка может дать дополнительные подсказки. Вы также можете попробовать skip_archive: True.   -  person shang    schedule 05.02.2011
comment
Спасибо. Я попробую это. Я также пробовал другие вещи и получал другие сообщения об ошибках. Эта ветка становится слишком длинной, чтобы кто-либо мог ее прочитать, поэтому я собираюсь закрыть ее и подумать, как переформулировать проблему в более кратких терминах, учитывая то, что я уже узнал. Если я повторно опубликую переформулированный вопрос на этом форуме, я включу ссылку на это более длинное исходное сообщение. Еще раз спасибо.   -  person MedicalMath    schedule 06.02.2011
comment
Возможно, никакая оптимизация не исправит это. У меня есть приложение, которое использует matplotlib 1.0.0, numpy 1.6.1, scipy 0.10.0, wx 2.8.12.1. Я могу успешно заморозить его с помощью py2exe (в GUI2Exe) с оптимизацией = 0, сжатием = 2, пакетом файлов = 1. Но при оптимизации = 1 или 2 я получаю сообщение об ошибке, похожее на ваше.   -  person otterb    schedule 14.02.2012


Ответы (3)


Похоже, проблема упомянута внизу: http://www.py2exe.org/index.cgi/MatPlotLib

Похоже, вам нужно внести несколько небольших изменений в mlab.py:

psd.__doc__ = psd.__doc__ % kwdocd

to

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

Если вы еще не видели эту страницу, вот как я туда попал: http://www.py2exe.org/index.cgi/WorkingWithVariousPackagesAndModules

person Guy Sirton    schedule 07.02.2011

Как уже упоминалось, 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
person rdchambers    schedule 10.02.2011

Возможно, это просто я глуп, но почему бы вам не попробовать обновить свой scipy с 0.8.0b1 до 0.8.0 и сделать то же самое с matplotlib? Numpy 1.4.1 все еще должен быть в порядке.

person madtowneast    schedule 18.03.2011