def create_py3_base_library(libzip_filename, graph):
"""
Package basic Python modules into .zip file. The .zip file with basic
modules is necessary to have on PYTHONPATH for initializing libpython3
in order to run the frozen executable with Python 3.
"""
# TODO Replace this function with something better or something from standard Python library.
# Helper functions.
def _write_long(f, x):
"""
Write a 32-bit int to a file in little-endian order.
"""
f.write(bytes([x & 0xff,
(x >> 8) & 0xff,
(x >> 16) & 0xff,
(x >> 24) & 0xff]))
# Construct regular expression for matching modules that should be bundled
# into base_library.zip.
# Excluded are plain 'modules' or 'submodules.ANY_NAME'.
# The match has to be exact - start and end of string not substring.
regex_modules = '|'.join([r'(^%s$)' % x for x in PY3_BASE_MODULES])
regex_submod = '|'.join([r'(^%s\..*$)' % x for x in PY3_BASE_MODULES])
regex_str = regex_modules + '|' + regex_submod
module_filter = re.compile(regex_str)
try:
# Remove .zip from previous run.
if os.path.exists(libzip_filename):
os.remove(libzip_filename)
logger.debug('Adding python files to base_library.zip')
# Class zipfile.PyZipFile is not suitable for PyInstaller needs.
with zipfile.ZipFile(libzip_filename, mode='w') as zf:
zf.debug = 3
for mod in graph.flatten():
if type(mod) in (modulegraph.SourceModule, modulegraph.Package):
# Bundling just required modules.
if module_filter.match(mod.identifier):
st = os.stat(mod.filename)
timestamp = int(st.st_mtime)
size = st.st_size & 0xFFFFFFFF
# Name inside a zip archive.
# TODO use .pyo suffix if optimize flag is enabled.
if type(mod) is modulegraph.Package:
new_name = mod.identifier.replace('.', os.sep) + os.sep + '__init__' + '.pyc'
else:
new_name = mod.identifier.replace('.', os.sep) + '.pyc'
# Write code to a file.
# This code is similar to py_compile.compile().
with io.BytesIO() as fc:
# Prepare all data in byte stream file-like object.
fc.write(BYTECODE_MAGIC)
_write_long(fc, timestamp)
_write_long(fc, size)
marshal.dump(mod.code, fc)
zf.writestr(new_name, fc.getvalue())
except Exception as e:
logger.error('base_library.zip could not be created!')
raise
评论列表
文章目录