I have a small application built with PyQt4 that I'm trying to freeze with cx_freeze, but I'm running into an issue with cx_freeze including some of my own modules that are required for the application to work.
I have two modules that are imported in my application that are located in a folder above where the application is located. I.e.:
Application path:
Python\DataViewer-PyQt4\DataViewer.py
Other modules:
Python\My Analysis Packages\Ephystools
Python\My Analysis Packages\PrairieAnalysis
In my application I import these by using (if they're not in my python path already)
sys.path.append(os.path.abspath('../My Analysis Packages'))
I have tried including PrairieAnalysis and EphysTools in both 'includes' and 'packages' in my setup.py file. I have tried including 'My Analysis Packages' as well. I have tried providing the paths to these as well.
They all contain init.py files, as the actual application is capable of importing them just fine.
If I put PrairieAnalysis and/or EphysTools in the 'includes' list then setup.py build returns an ImportError:
File "C:\Anaconda3\lib\site-packages\cx_Freeze\finder.py", line 386, in _ImportModule
raise ImportError("No module named %r" % name)
ImportError: No module named 'PrairieAnalysis'
If I leave them out of 'includes' setup.py build completes, but then when I go to open the application I get that same error.
I've looked through the various cx_freeze module import questions but none seem to have dealt with this particular scenario.
My actual setup.py:
# -*- coding: utf-8 -*-
import sys
from cx_Freeze import setup, Executable
base = None
if sys.platform == 'win32':
base = 'Win32GUI'
options = {
'build_exe': {
'includes': ['atexit', 'PrairieAnalysis', 'EphysTools'],
}
}
executables = [
Executable('DataViewer.py', base=base)
]
setup(name='DataViewer',
version='0.1',
description='Application for viewing Prairie-generated csv data files',
options=options,
executables=executables
)
Edit 1: Output from os.getcwd() in setup.py file:
D:\OneDrive\Documents\Python\DataViewer-PyQt4
Output from sys.path in setup.py file:
['D:\\OneDrive\\Documents\\Python\\DataViewer-PyQt4', 'D:\\OneDrive\\Documents\\Python\\My Analysis Packages', 'C:\\Anac
onda3\\python34.zip', 'C:\\Anaconda3\\DLLs', 'C:\\Anaconda3\\lib', 'C:\\Anaconda3', 'C:\\Anaconda3\\lib\\site-packages',
'C:\\Anaconda3\\lib\\site-packages\\Sphinx-1.2.3-py3.4.egg', 'C:\\Anaconda3\\lib\\site-packages\\win32', 'C:\\Anaconda3
\\lib\\site-packages\\win32\\lib', 'C:\\Anaconda3\\lib\\site-packages\\Pythonwin', 'C:\\Anaconda3\\lib\\site-packages\\r
unipy-0.1.1-py3.4.egg', 'C:\\Anaconda3\\lib\\site-packages\\setuptools-7.0-py3.4.egg']
Edit 2:
So I've also tried using py2exe and I run into the same issue. If I include the packages in "includes" I get the following traceback:
Traceback (most recent call last):
File "setup.py", line 7, in <module>
setup(windows=['DataViewer.py'], options={"py2exe": {"includes" :["sip", "PyQt4.QtCore", "PyQt4.QtGui", "PrairieAnal
ysis", "EphysTools"]}})
File "C:\Anaconda3\lib\distutils\core.py", line 148, in setup
dist.run_commands()
File "C:\Anaconda3\lib\distutils\dist.py", line 955, in run_commands
self.run_command(cmd)
File "C:\Anaconda3\lib\distutils\dist.py", line 974, in run_command
cmd_obj.run()
File "C:\Anaconda3\lib\site-packages\py2exe\distutils_buildexe.py", line 188, in run
self._run()
File "C:\Anaconda3\lib\site-packages\py2exe\distutils_buildexe.py", line 267, in _run
builder.analyze()
File "C:\Anaconda3\lib\site-packages\py2exe\runtime.py", line 164, in analyze
mf.import_hook(modname)
File "C:\Anaconda3\lib\site-packages\py2exe\mf3.py", line 120, in import_hook
module = self._gcd_import(name)
File "C:\Anaconda3\lib\site-packages\py2exe\mf3.py", line 274, in _gcd_import
return self._find_and_load(name)
File "C:\Anaconda3\lib\site-packages\py2exe\mf3.py", line 318, in _find_and_load
loader = importlib.find_loader(name, path)
File "C:\Anaconda3\lib\importlib\__init__.py", line 87, in find_loader
name=name)
ImportError: namespace packages do not have loaders
In this case I put my two packages (PrairieAnalysis and EphysTools) into my site-packages folder. Why are my packages being treated differently than the other packages?
Edit 3: So I have gotten py2exe to work by using the following setup script:
from distutils.core import setup
import py2exe
import PrairieAnalysis.pv_import
import EphysTools.utilities
includes = ["sip", "PyQt4.QtCore", "PyQt4.QtGui", "PrairieAnalysis", "EphysTools", "lxml._elementpath"]
packages = ["PrairieAnalysis", "EphysTools"]
setup(windows=['DataViewer.py'], options={"py2exe": {"includes" : includes,
"packages": packages}})
just importing PrairieAnalysis and EphysTools alone didn't work though, nor did doing
from PrairieAnalysis import *
from EphysTools import *
Adding those import statements to my cx_freeze setup.py script, however, does not fix the issue.
Edit 4:
>>> import PrairieAnalysis
>>> print(PrairieAnalysis.__file__)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute '__file__'
>>> print(PrairieAnalysis.__init__)
<method-wrapper '__init__' of module object at 0x0000000002B9C9F8>
Edit 5:
>>> os.listdir('D:\\OneDrive\\Documents\\Python\\My Analysis Packages')
['.idea', 'EphysTools', 'PrairieAnalysis', '__init___.py']
>>> os.listdir('D:\\OneDrive\\Documents\\Python\\My Analysis Packages\\PrairieAnalysis')
['misc_code.py', 'pv_import.py', 'pxml_parse.py', '__init___.py', '__pycache__']
>>> os.listdir('D:\\OneDrive\\Documents\\Python\\My Analysis Packages\\EphysTools')
['synaptics.py', 'utilities.py', '__init___.py', '__pycache__']
You need to modify sys.path
in your setup.py script in the same way that you do in your application. cx_Freeze looks at sys.path to find the modules and packages to include in your build, so if the directory containing those packages is not on sys.path, it can't find them.
Edit: It turned out that the problem was a misnamed __init__.py
file. The package was still importable as a PEP 420 namespace package, but cx_Freeze doesn't handle those yet.