regebro / tzlocal

A Python module that tries to figure out what your local timezone is
MIT License
184 stars 58 forks source link

Packaging tzlocal #115

Closed CribberSix closed 2 years ago

CribberSix commented 2 years ago

When trying to package tzlocal into an executable with PyInstaller, there occurs a weird error. I first stumbled across it when trying to create an executable from another package that depends on tzlocal, but the error is limited to tzlocal (I tried packaging the 4 lines of code below and got the same error).

The following code works fine when I execute it in PyCharm / via Console, but once packaged, it looks for a file that doesn't exist on my windows and crashes while trying to handle the error.

Code

import datetime
import tzlocal
print(datetime.datetime.now().__format__('%a, %d %b %Y %H:%M:%S %z'))
print(datetime.datetime.now(tzlocal.get_localzone()).__format__('%a, %d %b %Y %H:%M:%S %z'))

Packaging

pyinstaller --onefile --windowed test.py  # to create the spec file
pyinstaller test.spec    # after adapting the spec file (see below for hidden import configuration) 

Error

I looked up the path, but while the directory _MEI110002 exists, there is no directory called tzdata within it. I'm guessing that the package then tried to handle the error in other ways, but failed twice more.

Traceback (most recent call last):
  File "importlib\resources.py", line 97, in open_binary
FileNotFoundError: [Errno 2] No such file or directory: 'C:\\Users\\myusername\\AppData\\Local\\Temp\\_MEI110002\\tzdata\\zoneinfo\\Europe\\Berlin'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "zoneinfo\_common.py", line 12, in load_tzdata
  File "importlib\resources.py", line 111, in open_binary
FileNotFoundError: 'Berlin' resource not found in 'tzdata.zoneinfo.Europe'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "test.py", line 4, in <module>
  File "tzlocal\win32.py", line 98, in get_localzone
  File "zoneinfo\_common.py", line 24, in load_tzdata
zoneinfo._common.ZoneInfoNotFoundError: 'No time zone found with key Europe/Berlin'

Spec file

The spec from which I built the executable - I had to manually add tzdata as PyInstaller didn't see the second level import:

from PyInstaller.utils.hooks import collect_submodules
tzlocal_p = collect_submodules('tzlocal')
tzdata_p = collect_submodules('tzdata')

a = Analysis(..... 
                      hiddenimports=tzlocal_p+tzdata_p,
                  ..... )
regebro commented 2 years ago

So, this seems to be that the localzone library can't find the files provided by the tzdata library.

I do not currently know enough about how pyinstaller works to know why this is and how to fix it.

regebro commented 2 years ago

I think this probably is a question for Pyinstaller people, how to include the tzdata library so its data files are included.