#-----------------------------------------------------------------------------
|
# Copyright (c) 2023, PyInstaller Development Team.
|
#
|
# This file is distributed under the terms of the Apache License 2.0
|
#
|
# The full license is available in LICENSE, distributed with
|
# this software.
|
#
|
# SPDX-License-Identifier: Apache-2.0
|
#-----------------------------------------------------------------------------
|
|
def _pyi_rthook():
|
import sys
|
|
# `tensorflow` versions prior to 2.3.0 attempt to use `site.USER_SITE` in path/string manipulation functions.
|
# As frozen application runs with disabled `site`, the value of this variable is `None`, and causes path/string
|
# manipulation functions to raise an error. As a work-around, we set `site.USER_SITE` to an empty string, which is
|
# also what the fake `site` module available in PyInstaller prior to v5.5 did.
|
import site
|
|
if site.USER_SITE is None:
|
site.USER_SITE = ''
|
|
# The issue described about with site.USER_SITE being None has largely been resolved in contemporary `tensorflow`
|
# versions, which now check that `site.ENABLE_USER_SITE` is set and that `site.USER_SITE` is not None before
|
# trying to use it.
|
#
|
# However, `tensorflow` will attempt to search and load its plugins only if it believes that it is running from
|
# "a pip-based installation" - if the package's location is rooted in one of the "site-packages" directories. See
|
# https://github.com/tensorflow/tensorflow/blob/6887368d6d46223f460358323c4b76d61d1558a8/tensorflow/api_template.__init__.py#L110C76-L156
|
# Unfortunately, they "cleverly" infer the module's location via `inspect.getfile(inspect.currentframe())`, which
|
# in the frozen application returns anonymized relative source file name (`tensorflow/__init__.py`) - so we need one
|
# of the "site directories" to be just "tensorflow" (to fool the `_running_from_pip_package()` check), and we also
|
# need `sys._MEIPASS` to be among them (to load the plugins from the actual `sys._MEIPASS/tensorflow-plugins`).
|
# Therefore, we monkey-patch `site.getsitepackages` to add those two entries to the list of "site directories".
|
|
_orig_getsitepackages = getattr(site, 'getsitepackages', None)
|
|
def _pyi_getsitepackages():
|
return [
|
sys._MEIPASS,
|
"tensorflow",
|
*(_orig_getsitepackages() if _orig_getsitepackages is not None else []),
|
]
|
|
site.getsitepackages = _pyi_getsitepackages
|
|
# NOTE: instead of the above override, we could also set TF_PLUGGABLE_DEVICE_LIBRARY_PATH, but that works only
|
# for tensorflow >= 2.12.
|
|
|
_pyi_rthook()
|
del _pyi_rthook
|