I\'m having a problem distributing an application that utilizes pytz. I\'m using Py2Exe to create an executable from my Python source.
For a simpl
Zipping the zoneinfo manually (as described by Jason S) helped indeed for building the package on one of my computers. However, when I built the package on another computer - the error was back! Finding the reason took me a while - so I'd better share.
The proposed solution doesn't work with new pytz-versions (at least with 2014.7)! Digging why this is revealed that pytz changed the format of the zoneinfo files from pyc to some binary format. To me it looks like, with this change they "broke" the option to pack pytz into a zip, since the builtin zipimport mechanism of python doesn't work for loading binary files. Actually, this problem should be fixed by pytz but for now I found another solution:
Practically, this means within your setup.py replace the pytz-zipping with
import pytz, os, shutil
srcDir = os.path.dirname( pytz.__file__ )
dstDir = os.path.join( 'dist', 'pytz' )
shutil.copytree( srcDir, dstDir, ignore = shutil.ignore_patterns('*.py') )
and move pytz from the "packages"-option to "excludes":
options = {
"py2exe" : {
"compressed": 1,
"optimize": 2,
"packages": [],
"excludes": ['pytz']
}
}
At the main entry of your program (to make sure it is executed before importing pytz), you would have to add something like:
import os, sys
basePath = os.path.dirname( os.path.abspath( sys.argv[0] ) )
sys.path.insert( 0, basePath )
A simple solution would be to add the zoneinfo directory, from the pytz module in the python site-packages directory, to the library.zip.
To do this automatically, I followed the solution the project Google Transit Data Feed used, from: http://code.google.com/p/googletransitdatafeed/source/browse/trunk/python/setup.py
My modified setup.py now looks like:
from distutils.core import setup
import glob
import py2exe
options = {
"py2exe" : {
"compressed": 1,
"optimize": 2,
'packages': ['pytz'],
}
}
setup(console=['pytz_test.py'], options=options)
import pytz
import os
import zipfile
zipfile_path = os.path.join("dist/" 'library.zip')
z = zipfile.ZipFile(zipfile_path, 'a')
zoneinfo_dir = os.path.join(os.path.dirname(pytz.__file__), 'zoneinfo')
disk_basedir = os.path.dirname(os.path.dirname(pytz.__file__))
for absdir, directories, filenames in os.walk(zoneinfo_dir):
assert absdir.startswith(disk_basedir), (absdir, disk_basedir)
zip_dir = absdir[len(disk_basedir):]
for f in filenames:
z.write(os.path.join(absdir, f), os.path.join(zip_dir, f))
z.close()
(Answered by asker)