py2exe and numpy not getting along - python
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.
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
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
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.
Related
servable panel app ModuleNotFoundError on included local module
I'm having issues deploying my Panel app to be served up as HTML. Following instructions at https://panel.holoviz.org/user_guide/Running_in_Webassembly.html, with script.py as import panel as pn from mymodule import MyObj pn.extension('terminal', 'tabulator', sizing_mode="stretch_width") gspec = pn.GridSpec(sizing_mode='stretch_width', max_height=100, ncols=3) PI = MyObj() gspec[0, 0:1] = PI.tabs gspec[0, 2] = PI.view pn.Column( "Text Text Text" , gspec ).servable() and mymodule/__init__.py: __version__ = '0.1.0' from .my_obj import MyObj and mymodule/my_obj.py: from .param_classes import ClassA from .param_classes import ClassB # etc from .compute_obj import ComputeObj class MyObj(object): # all the details of the panel build, calling in turn # param classes detailed in another file, and also calling another module # to handle all the computation behind the panel panel serve script.py --autoreload works perfectly, but $ panel convert script.py --to pyodide-worker --out pyodide $ python3 -m http.server does not work. I get a big display at http://localhost:8000/pyodide/script.html: ModuleNotFoundError: no module named 'mymodule', and an infinite loop spinning graphic, and in the Developer Tools Console output: pyodide.asm.js:10 Uncaught (in promise) PythonError: Traceback (most recent call last): File "/lib/python3.10/asyncio/futures.py", line 201, in result raise self._exception File "/lib/python3.10/asyncio/tasks.py", line 232, in __step result = coro.send(None) File "/lib/python3.10/site-packages/_pyodide/_base.py", line 506, in eval_code_async await CodeRunner( File "/lib/python3.10/site-packages/_pyodide/_base.py", line 359, in run_async await coroutine File "<exec>", line 11, in <module> ModuleNotFoundError: No module named 'mymodule' at new_error (pyodide.asm.js:10:218123) at pyodide.asm.wasm:0xdef7c at pyodide.asm.wasm:0xe37ae at method_call_trampoline (pyodide.asm.js:10:218037) at pyodide.asm.wasm:0x126317 at pyodide.asm.wasm:0x1f6f2e at pyodide.asm.wasm:0x161a32 at pyodide.asm.wasm:0x126827 at pyodide.asm.wasm:0x126921 at pyodide.asm.wasm:0x1269c4 at pyodide.asm.wasm:0x1e0697 at pyodide.asm.wasm:0x1da6a5 at pyodide.asm.wasm:0x126a07 at pyodide.asm.wasm:0x1e248c at pyodide.asm.wasm:0x1e00d9 at pyodide.asm.wasm:0x1da6a5 at pyodide.asm.wasm:0x126a07 at pyodide.asm.wasm:0xe347a at Module.callPyObjectKwargs (pyodide.asm.js:10:119064) at Module.callPyObject (pyodide.asm.js:10:119442) at wrapper (pyodide.asm.js:10:183746) I should add that I'm using poetry to manage packages and build the venv, and I'm operating all the above from within the activated .venv (via poetry shell) I've tried all the tips and tricks around append the local path to sys.path. Looking at the .js file that the convert utility generates, I gather it would work if all the code were in one file, but forcing bad coding practice doesn't sound right. I imagine there could be some kind of C++ build-style --include argument to panel convert, but there are no man pages, and the closest I can get with online documentation is --requirements ./mymodule, but no joy. Could anybody please advise?
How to store the results of a command to a variable?
I'm trying to build a context menu that will show a tree structure of all my packages and their resources. Something like this terrible MS Paint rendering I drew: I have PackageResourceViewer installed. It offers commands that show in a window. But I would like to use them to populate these sub-context menues: get_packages_list that I think will populate the first sub-menu (packages) list_package_files that should populate each subsequent sub-menu However, I'm not sure how to get the output of these into a context menu. I've been looking at python (writing a sublime plugin for this). How do I get the output of these commands into a variable? My Code import sublime import sublime_plugin class ExampleCommand(sublime_plugin.TextCommand): def run(self, edit): self.view.insert(edit, 0, package_resource_viewer) But it gives me this error: >>> view.window().run_command("example") Traceback (most recent call last): File "C:\Program Files\Sublime Text 3\sublime_plugin.py", line 818, in run_ return self.run(edit) File "C:\Users\heete\AppData\Roaming\Sublime Text 3\Packages\User\hello_world.py", line 7, in run self.view.insert(edit, 0, package_resource_viewer) NameError: global name 'package_resource_viewer' is not defined Obviously I haven't gotten far, but I can't even get the output of this to show in the buffer.
You can import and access those commands. I made a minimal example, which prints the packages to the current view. However output the to a context/sidebar menu seems to be harder, because they are usually static and you cannot just create one dynamically. (You may try to create a static menu file via a command.) import sublime_plugin from PackageResourceViewer.package_resources import ( get_packages_list, list_package_files ) class ExampleListPackagesCommand(sublime_plugin.TextCommand): def run(self, edit): packages = get_packages_list() insert_sb = [] insert_sb.append("Installed Packages:") insert_sb.extend(packages) for package in packages: insert_sb.append("") insert_sb.append(package) package_files = list_package_files(package) insert_sb.extend("\t" + pf for pf in package_files) self.view.insert(edit, 0, "\n".join(insert_sb))
keyring module is not included while packaging with py2exe
I am making an app using python 2.7 on windows and keyring-3.2.1 . In my python code on eclipse, I used import keyring keyring.set_password("service","jsonkey",json_res) json_res= keyring.get_password("service","jsonkey") is working fine as I am storing json response in keyring. But, when I converted python code into exe by using py2exe, it shows import error keyring while making dist. Please suggest how to include keyring in py2exe. Traceback (most recent call last): File "APP.py", line 8, in <module> File "keyring\__init__.pyc", line 12, in <module> File "keyring\core.pyc", line 15, in <module> File "keyring\util\platform_.pyc", line 4, in <module> File "keyring\util\platform.pyc", line 29, in <module> AttributeError: 'module' object has no attribute 'system' platform_.py code is : from __future__ import absolute_import import os import platform def _data_root_Windows(): try: root = os.environ['LOCALAPPDATA'] except KeyError: # Windows XP root = os.path.join(os.environ['USERPROFILE'], 'Local Settings') return os.path.join(root, 'Python Keyring') def _data_root_Linux(): """ Use freedesktop.org Base Dir Specfication to determine storage location. """ fallback = os.path.expanduser('~/.local/share') root = os.environ.get('XDG_DATA_HOME', None) or fallback return os.path.join(root, 'python_keyring') # by default, use Unix convention data_root = globals().get('_data_root_' + platform.system(), _data_root_Linux) platform.py code is: import os import sys # While we support Python 2.4, use a convoluted technique to import # platform from the stdlib. # With Python 2.5 or later, just do "from __future__ import absolute_import" # and "import platform" exec('__import__("platform", globals=dict())') platform = sys.modules['platform'] def _data_root_Windows(): try: root = os.environ['LOCALAPPDATA'] except KeyError: # Windows XP root = os.path.join(os.environ['USERPROFILE'], 'Local Settings') return os.path.join(root, 'Python Keyring') def _data_root_Linux(): """ Use freedesktop.org Base Dir Specfication to determine storage location. """ fallback = os.path.expanduser('~/.local/share') root = os.environ.get('XDG_DATA_HOME', None) or fallback return os.path.join(root, 'python_keyring') # by default, use Unix convention data_root = globals().get('_data_root_' + platform.system(), _data_root_Linux)
The issue you're reporting is due to an environment that contains invalid modules, perhaps from an improper installation of one version of keyring over another. You will want to ensure that you've removed remnants of the older version of keyring. In particular, make sure there's no file called keyring\util\platform.* in your site-packages. After doing that, however, you'll encounter another problem. Keyring loads its backend modules programmatically, so py2exe won't detect them. To work around that, you'll want to add a 'packages' declaration to your py2exe options to specifically include the keyring.backends package. I invoked the following setup.py script with Python 2.7 to convert 'app.py' (which imports keyring) to an exe: from distutils.core import setup import py2exe setup( console=['app.py'], options=dict(py2exe=dict( packages='keyring.backends', )), ) The resulting app.exe will import and invoke keyring.
Create and use settings module in Python
I am new to Python so bear with me. I use the pyDev plugin fore eclipse. There are three files: tool.py: from gui import Tool_Window import wx import settings if __name__ == '__main__': window = wx.App() Tool_Window(None, settings.WindowHeader) window.MainLoop() Tool_Window.py: from Tool import settings import wx class Tool_Window(wx.Frame): def __init__(self, parent, title): super(Tool_Window,self).__init__(parent, title = title) self.SetDimensions(settings.WindowOpenX, settings.WindowOpenY, settings.WindowWidth, settings.WindowHeight) settings.py: WindowHeader = 'The SuperAwesome Tool' WindowOpenX = 500 WindowOpenY = 100 WindowWidth = 200 WindowHeight = 400 The "tool.py" file is in a package called "Tool", as is the "settings.py" file, and "Tool_Window" is in the package "gui". I am getting error messages from a previous file I had in the project, now renamed to the "settings.py". I have tried cleaning the project in Eclipse, but nothing happens. The error message looks like: Traceback (most recent call last): File "/home/oystein/workspaces/python/awesome.tool/src/Tool/tool.py", line 8, in <module> Tool_Window(None, settings.WindowHeader) File "/home/oystein/workspaces/python/awesome.tool/src/gui/__init__.py", line 12, in __init__ # ;-) AttributeError: class GeneralParameters has no attribute 'WindowParameters' Previously I had a class named GeneralParameters with a sub-class WindowParameters, as I wanted to access static variables for settings. I relaized Python couldn't do it like that and changed it to the "settings.py" file. I run the program from "tool.py" Can anyone see what's wrong here?
You are running stale byte-code, remove the .pyc files and rerun your code. The traceback reads the source from the .py file but is built from the bytecode, and the fact that is shows that the error is on a line that only consists of a comment is a hint that things are no longer in sync. Normally, Python will clean up the .pyc file when stale, but only if the .py modification time is newer.
Using psyco with py2exe?
In my main script, lets call this MyScript.py, I have it like this: import psyco psyco.full() And then my setup.py looks like this: from distutils.core import setup import py2exe, sys, os, glob sys.argv.append('py2exe') import psyco #speed up compilation psyco.full() def find_data_files(source,target,patterns): """Locates the specified data-files and returns the matches in a data_files compatible format. source is the root of the source data tree. Use '' or '.' for current directory. target is the root of the target data tree. Use '' or '.' for the distribution directory. patterns is a sequence of glob-patterns for the files you want to copy. """ if glob.has_magic(source) or glob.has_magic(target): raise ValueError("Magic not allowed in src, target") ret = {} for pattern in patterns: pattern = os.path.join(source,pattern) for filename in glob.glob(pattern): if os.path.isfile(filename): targetpath = os.path.join(target,os.path.relpath(filename,source)) path = os.path.dirname(targetpath) ret.setdefault(path,[]).append(filename) return sorted(ret.items()) setup( name="MyScript", version="1.0", description="a script that does something", author="Keelx", data_files=find_data_files('.','',[ 'gfx/*', 'data/*', ]), options={'py2exe': {'bundle_files': 1,'optimize': 2}}, windows=[{'script': "MyScript.py"}], zipfile=None, ) It creates a 'dist' folder, with the executable, a win9x executable, and the gfx and data folders next to the executable. However, when I run it it points me to a log which reads: Traceback (most recent call last): File "MyScript.py", line 16, in File "zipextimporter.pyo", line 82, in load_module File "psyco__init__.pyo", line 64, in WindowsError: [Error 3] The system cannot find the path specified: 'C:\Documents and Settings\Keelx\Desktop\MyScriptFolder\dist\MyScript.exe\psyco\_psyco.pyd' It would seem that the psyco module is not being put into the executable. I've been searching, and I haven't found a working solution to get py2exe to copy psyco over. And please refrain from posting solutions along the lines of 'don't use py2exe'. Thank you in advance whomever can help me out here.
Hunting down py2exe errors appears to be an art to me. That said, I will at least offer something to try. I py2exe'ed a psyco enabled python script and tossed it in the includes part of the setup. Thats the only part that looks different between your setup and my old one. options = {'py2exe': {'packages': [ 'IPython'], 'includes': ["psyco"], } } Also I was never able to enable optimize. It always caused random errors. Best to leave that one off in my experience. I think it was matplotlib that caused those errors. Hope this helps, Cheers,