1 2import os 3import runpy 4import shutil 5import sys 6import tempfile 7import zipfile 8 9from pathlib import PurePath 10 11 12sys.argv[0] = __loader__.archive 13 14# Set sys.executable to None. The real executable is available as 15# sys.argv[0], and too many things assume sys.executable is a regular Python 16# binary, which isn't available. By setting it to None we get clear errors 17# when people try to use it. 18sys.executable = None 19 20# Extract the shared libraries from the zip file into a temporary directory. 21# This works around the limitations of dynamic linker. Some Python libraries 22# reference the .so files relatively and so extracting only the .so files 23# does not work, so we extract the entire parent directory of the .so files to a 24# tempdir and then add that to sys.path. 25tempdir = None 26with zipfile.ZipFile(__loader__.archive) as z: 27 # any root so files or root directories that contain so files will be 28 # extracted to the tempdir so the linker load them, this minimizes the 29 # number of files that need to be extracted to a tempdir 30 extract_paths = {} 31 for member in z.infolist(): 32 if member.filename.endswith('.so'): 33 extract_paths[PurePath(member.filename).parts[0]] = member.filename 34 if extract_paths: 35 tempdir = tempfile.mkdtemp() 36 for member in z.infolist(): 37 if not PurePath(member.filename).parts[0] in extract_paths.keys(): 38 continue 39 if member.is_dir(): 40 os.makedirs(os.path.join(tempdir, member.filename)) 41 else: 42 z.extract(member, tempdir) 43 sys.path.insert(0, tempdir) 44try: 45 runpy._run_module_as_main("ENTRY_POINT", alter_argv=False) 46finally: 47 if tempdir is not None: 48 shutil.rmtree(tempdir) 49