pyminifier.py - The main module for minifying, obfuscating, and compressing Python code

Python Minifier: Reduces the size of (minifies) Python code for use on embedded platforms.

Performs the following:

  • Removes docstrings.
  • Removes comments.
  • Minimizes code indentation.
  • Joins multiline pairs of parentheses, braces, and brackets (and removes extraneous whitespace within).
  • Preserves shebangs and encoding info (e.g. “# – coding: utf-8 –”).
  • Optionally, produces a bzip2 or gzip-compressed self-extracting python script containing the minified source for ultimate minification. Added in version 1.4
  • Optionally, obfuscates the code using the shortest possible combination of letters and numbers for one or all of class names, function/method names, and variables. The options are --obfuscate or -O to obfuscate everything, --obfuscate-variables, --obfuscate-functions, and --obfuscate-classes to obfuscate things individually (say, if you wanted to keep your module usable by external programs). Added in version 2.0
  • Optionally, a value may be specified via –replacement-length to set the minimum length of random strings that are used to replace identifier names when obfuscating.
  • Optionally, if using Python 3, you may specify --nonlatin to use funky unicode characters when obfuscating. WARNING: This will result in some seriously hard-to-read code! Tip: Combine this setting with higher --replacement-length values to make the output even wackier. Added in version 2.0
  • Pyminifier can now minify/obfuscate an arbitrary number of Python scripts in one go. For example, ./pyminifier.py -O *.py will minify and obfuscate all files in the current directory ending in .py. To prevent issues with using differentiated obfuscated identifiers across multiple files, pyminifier will keep track of what replaces what via a lookup table to ensure foo_module.whatever is gets the same replacement across all source files. Added in version 2.0
  • Optionally, creates an executable zip archive (pyz) containing the minified/obfuscated source script and all implicit (local path) imported modules. This mechanism automatically figures out which source files to include in the .pyz archive by analyzing the script passed to pyminifier on the command line (listing all the modules your script uses is unnecessary). This is also the ultimate in minification/compression besting both the gzip and bzip2 compression mechanisms with the disadvantage that .pyz files cannot be imported into other Python scripts. Added in version 2.0

Just how much space can be saved by pyminifier? Here’s a comparison:

  • The pyminifier source (all six files) takes up about 164k.
  • Performing basic minification on all pyminifier source files reduces that to ~104k.
  • Minification plus obfuscation provides a further reduction to 92k.
  • Minification plus the base64-encoded gzip trick (–gzip) reduces it to 76k.
  • Minification plus gzip compression plus obfuscation is also 76k (demonstrating that obfuscation makes no difference when compression algorthms are used).
  • Using the –pyz option on pyminifier.py creates a ~14k .pyz file that includes all the aforementioned files.

Various examples and edge cases are sprinkled throughout the pyminifier code so that it can be tested by minifying itself. The way to test is thus:

$ python pyminifier.py pyminifier.py > minified_pyminifier.py
$ python minified_pyminifier.py pyminifier.py > this_should_be_identical.py
$ diff minified_pyminifier.py this_should_be_identical.py
$

If you get an error executing minified_pyminifier.py or this_should_be_identical.py isn’t identical to minified_pyminifier.py then something is broken.

Note

The test functions below are meaningless. They only serve as test/edge cases for testing pyminifier.

class pyminifier.pyminifier.test_class[source]

Testing indented decorators

pyminifier.pyminifier.test_decorator(f)[source]

Decorator that does nothing

pyminifier.pyminifier.test_empty_functions()[source]

This is a test function. This should be replaced with ‘def test_empty_functions(): pass’

pyminifier.pyminifier.test_function()[source]

This function encapsulates the edge cases to prevent them from invading the global namespace.

pyminifier.pyminifier.test_reduce_operators()[source]

Test the case where an operator such as an open paren starts a line