UnknownTimezoneError Exception Raised with Python Application Compiled with Py2Exe

后端 未结 2 931
攒了一身酷
攒了一身酷 2020-12-15 08:48

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

相关标签:
2条回答
  • 2020-12-15 09:35

    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:

    • Just copy the whole pytz directory directly into your dist directory
    • within your program, add the path of your main-exectutable to python's search path

    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 )
    
    0 讨论(0)
  • 2020-12-15 09:37

    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)

    0 讨论(0)
提交回复
热议问题