Lawrence Hudson, SF #401702: Modify co_filename in frozen programs

This patch was developed primarily to reduce the size of the
  frozen binary.  It is particularly useful when freezing for 'small'
  platforms, such as Palm OS, where you really want to save that
  last miserable byte.

  A limitation of this patch is that it does not provide any feedback
  about the replacements being made.  As the path matching
  is case-sensitive this may lead to unexpected behaviour for DOS
  and Windows people, eg
      > freeze.py -r C:\Python\Lib\=py\ goats.py
  should probably be:
      > freeze.py -r c:\python\lib\=py\ goats.py
This commit is contained in:
Guido van Rossum 2001-03-20 20:43:34 +00:00
parent b845cb0946
commit 6b767ac81a
2 changed files with 42 additions and 3 deletions

View file

@ -7,6 +7,7 @@ import os
import re
import string
import sys
import new
IMPORT_NAME = dis.opname.index('IMPORT_NAME')
IMPORT_FROM = dis.opname.index('IMPORT_FROM')
@ -49,7 +50,7 @@ class Module:
class ModuleFinder:
def __init__(self, path=None, debug=0, excludes = []):
def __init__(self, path=None, debug=0, excludes = [], replace_paths = []):
if path is None:
path = sys.path
self.path = path
@ -58,6 +59,8 @@ class ModuleFinder:
self.debug = debug
self.indent = 0
self.excludes = excludes
self.replace_paths = replace_paths
self.processed_paths = [] # Used in debugging only
def msg(self, level, str, *args):
if level <= self.debug:
@ -250,6 +253,8 @@ class ModuleFinder:
m = self.add_module(fqname)
m.__file__ = pathname
if co:
if self.replace_paths:
co = self.replace_paths_in_code(co)
m.__code__ = co
self.scan_code(co, m)
self.msgout(2, "load_module ->", m)
@ -369,6 +374,32 @@ class ModuleFinder:
mods.sort()
print "?", key, "from", string.join(mods, ', ')
def replace_paths_in_code(self, co):
new_filename = original_filename = os.path.normpath(co.co_filename)
for f,r in self.replace_paths:
if original_filename.startswith(f):
new_filename = r+original_filename[len(f):]
break
if self.debug and original_filename not in self.processed_paths:
if new_filename!=original_filename:
self.msgout(2, "co_filename %r changed to %r" \
% (original_filename,new_filename,))
else:
self.msgout(2, "co_filename %r remains unchanged" \
% (original_filename,))
self.processed_paths.append(original_filename)
consts = list(co.co_consts)
for i in range(len(consts)):
if isinstance(consts[i], type(co)):
consts[i] = self.replace_paths_in_code(consts[i])
return new.code(co.co_argcount, co.co_nlocals, co.co_stacksize,
co.co_flags, co.co_code, tuple(consts), co.co_names,
co.co_varnames, new_filename, co.co_name,
co.co_firstlineno, co.co_lnotab)
def test():
# Parse command line