pyminifier

Pyminifier is a Python code minifier, obfuscator, and compressor.

Note

Overview

When you install pyminifier it should automatically add a 'pyminifier' executable to your $PATH. This executable has a number of command line arguments:

$ pyminifier --help
Usage: pyminifier [options] "<input file>" Options:
--version             show program's version number and exit
-h, --help            show this help message and exit
-o <file path>, --outfile=<file path>
                      Save output to the given file.
-d <file path>, --destdir=<file path>
                      Save output to the given directory. This option is
                        required when handling multiple files. Defaults to
                        './minified' and will be created if not present.
--nominify            Don't bother minifying (only used with --pyz).
--use-tabs            Use tabs for indentation instead of spaces.
--bzip2               bzip2-compress the result into a self-executing python
                        script. Only works on stand-alone scripts without
                        implicit imports.
--gzip                gzip-compress the result into a self-executing python
                        script. Only works on stand-alone scripts without
                        implicit imports.
--lzma                lzma-compress the result into a self-executing python
                        script. Only works on stand-alone scripts without
                        implicit imports.
--pyz=<name of archive>.pyz
                      zip-compress the result into a self-executing python
                        script. This will create a new file that includes any
                        necessary implicit (local to the script) modules.
                        Will include/process all files given as arguments to
                        pyminifier.py on the command line.
-O, --obfuscate       Obfuscate all function/method names, variables, and
                        classes. Default is to NOT obfuscate.
--obfuscate-classes   Obfuscate class names.
--obfuscate-functions
                      Obfuscate function and method names.
--obfuscate-variables
                      Obfuscate variable names.
--obfuscate-import-methods
                      Obfuscate globally-imported mouled methods (e.g.
                        'Ag=re.compile').
--obfuscate-builtins  Obfuscate built-ins (i.e. True, False, object,
                        Exception, etc).
--replacement-length=1
                      The length of the random names that will be used when
                        obfuscating identifiers.
--nonlatin            Use non-latin (unicode) characters in obfuscation
                        (Python 3 only). WARNING: This results in some
                        SERIOUSLY hard-to-read code.
--prepend=<file path>
                      Prepend the text in this file to the top of our
                        output. e.g. A copyright notice. 另外就是:

Opy 1.1.7

OPY - Obfuscator for Python, string obfuscation added

Latest Version: 1.1.28

The famous Phaistos Disc from Crete, obfuscation unbroken after thousands of years.

Opy will obfuscate your extensive, real world, multi module Python source code for free!
And YOU choose per project what to obfuscate and what not, by editting the config file:

  • You can recursively exclude all identifiers from certain modules from obfuscation.
  • You can exclude human readable configuration files containing Python code.
  • You can use getattr, setattr, exec and eval by excluding the identifiers they use.
  • You can even obfuscate module file names and string literals.
  • You can run your obfuscated code from any platform.

What’s new:

  • Shebang and encoding lines are handled properly
  • Unicode and raw strings are handled properly
  • Underscore at the start of a name will be preserved in obfuscation
  • Names are obfuscated as hard to read sequences of 1’s and l’s
  • String literals can be obfuscated, this is reversible but poses an extra barrier
  • Comments and string literals can be exempted from obfuscation by inserting a special marker
  • Several bug fixes
  • Name changed from Pyo to Opy

Bug reports and feature requests are most welcome and will be taken under serious consideration on a non-committal basis

Installation:

  • Download and unzip Opy into an arbitrary directory of your computer.
  • You only need the files opy.py and py_config.txt. They are in the opy subdirectory of your unzipped Opy version.
  • Put opy.py or a script to launch it in the path of your OS, or simply copy opy.py to the topdirectory of your project.

Use:

  • For safety, backup your sourcecode and valuable data to an off-line medium.
  • Put a copy of opy_config.txt in the top directory of your project.
  • Adapt it to your needs according to the remarks in opy_config.txt.
  • This file only contains plain Python and is exec’ed, so you can do anything clever in it.
  • Open a command window, go to the top directory of your project and run opy.py from there.
  • If the topdirectory of your project is e.g. ../work/project1 then the obfuscation result wil be in ../work/project1_opy.
  • Further adapt opy_config.txt until you’re satisfied with the result.
  • Type ‘opy ?’ or ‘python opy.py ?’ (without the quotes) on the command line to display a help text and the licence.

Important remark:

  • Obfuscate your Python code only when stricktly needed. Freedom is
    one of the main benefits of the Python community. In line with this the
    source of Opy is not obfuscated.

Example of obfuscated code:

import Tkinter as l1111lll1
import tkFileDialog
import os from util import * from l1l111l import *
from l1llll1 import * l1l1lll1l1l1 = 35
l1l11l1ll1 = 16 class l111l1l111l (l1111lll1.Frame, l1lll11ll1):
def __init__ (self, parent):
l1111lll1.Frame.__init__ (self, parent)
l1lll11ll1.__init__ (self) self.l1l1ll11llll = [] self.l1l1ll11llll.append (l1111lll1.Frame (self, width = l1l1llll1111, height = l1l11l111l))
self.l1l1ll11llll [-1] .pack (side = l1llll (u'ࡶࡲࡴࠬ')) self.l1l1ll1ll11l = l1111lll1.LabelFrame (self, text = l1llll (u'ࡒࡦࡵࡤࡱࡵࡲࡩ࡯ࡩ࠸'), padx = 5)
self.l1l1ll1ll11l.pack (side = l1llll (u'ࡺ࡯ࡱࠢ'), fill = l1llll (u'ࡦࡴࡺࡨࠧ'), expand = True)

Known limitations:

  • A comment after a string literal should be preceded by whitespace.
  • A ‘ or ” inside a string literal should be escaped with \ rather then doubled.
  • A # in a string literal can only be used at the start, so use ‘p”#”r’ rather than ‘p#r’.
  • Obfuscation of string literals is unsuitable for sensitive information since it can be trivially broken

还有:

 

Using pyobfuscate

One is obfuscation. I like a package called pyobfuscate. It transforms your normal and clearly written (right?) Python source code into new source code that is hard to read, by making changes to whitespace and names, stripping comments, removing functions, etc.

The package doesn’t seem to be on PyPI, but you can install it from the Github repo:

git clone https://github.com/astrand/pyobfuscate.git
cd pyobfuscate/
python setup.py install
1
2
3
cd pyobfuscate/
python setup.py install

Let’s try it out. Save the following code in example.py :

def fibonacci(n):
if n == 0: return 0
if n == 1: return 1
return fibonacci(n-1) + fibonacci(n-2)

def main():
for i in range(10):
result = fibonacci(1)

if __name__ == "__main__":
main()

1
2
3
4
5
6
7
8
9
10
11
12
def fibonacci(n):
    if n == 0: return 0
    if n == 1: return 1
    return fibonacci(n-1) + fibonacci(n-2)
 
 
def main():
    for i in range(10):
        result = fibonacci(1)
 
if __name__ == "__main__":
    main()

Obfuscate it using the pyobfuscate  command, which should be on your path now that you have installed the package:

pyobfuscate example.py
1
pyobfuscate example.py

Thee obfuscated code will be printed to the console:

def oo000 ( n ) :
if n == 0 : return 0
if n == 1 : return 1
return oo000 ( n - 1 ) + oo000 ( n - 2 )
if 9 - 9: Ii . o0o00Oo0O - iI11I1II1I1I
if 71 - 71: ii
def iIIii1IIi ( ) :
for o0OO00 in range ( 10 ) :
oo = oo000 ( 1 )
if 27 - 27: oO0OooOoO * o0Oo
if __name__ == "__main__" :
iIIii1IIi ( )
1
2
3
4
5
6
7
8
9
10
11
12
def oo000 ( n ) :
if n == 0 : return 0
if n == 1 : return 1
return oo000 ( n - 1 ) + oo000 ( n - 2 )
if 9 - 9: Ii . o0o00Oo0O - iI11I1II1I1I
if 71 - 71: ii
def iIIii1IIi ( ) :
for o0OO00 in range ( 10 ) :
  oo = oo000 ( 1 )
  if 27 - 27: oO0OooOoO * o0Oo
if __name__ == "__main__" :
iIIii1IIi ( )

That’s pretty illegible!

Unfortunately pyobfuscate only works on one source file at a time, so it’s not really suitable for large projects. It also appears to only work with Python 2 at the moment.

Distributing bytecode

Another, arguably easier, method is to just distribute the .pyc files. The Python standard library includes a compileall module that can scan your source directory and compile all of your files into Python bytecode. Then you can distribute them without the source files. The .pyc files can still be decompiled into source code, but the code will not be as readable as it was before.

One problem with this method is that the initial .py script that you run cannot be compiled in this way. You can solve this problem by making a simple wrapper script that gives away no information about your program.

from mymodule import main

if __name__ == "__main__":
    main()

1
2
3
4
from mymodule import main
 
if __name__ == "__main__":
    main()

These two methods are really just a deterrent, not a secure way of hiding the code.

If you want something a bit more robust, you should take a look at Nuitka, which compiles Python code to C++, so you can compile that and just distribute the executable. It seems to be broadly compatible with different libraries and different versions of Python.


compileall – Byte-compile Source Files

Purpose: Convert source files to byte-compiled version.
Available In: 1.4

The compileall module finds Python source files and compiles them to the byte-code representation, saving the results in .pyc or .pyo files.

Compiling One Directory

compile_dir() is used to recursively scan a directory and byte-compile the files within it.

import compileall

compileall.compile_dir('examples')

By default, all of the subdirectories are scanned to a depth of 10. When using a version control system such as subversion, this can lead to unnecessary scanning, as seen here:

$ python compileall_compile_dir.py

Listing examples ...
Listing examples/.svn ...
Listing examples/.svn/prop-base ...
Listing examples/.svn/text-base ...
Compiling examples/a.py ...
Listing examples/subdir ...
Listing examples/subdir/.svn ...
Listing examples/subdir/.svn/prop-base ...
Listing examples/subdir/.svn/text-base ...
Compiling examples/subdir/b.py ...

To filter directories out, use the rx argument to provide a regular expression to match the names to exclude.

import compileall
import re compileall.compile_dir('examples',
rx=re.compile(r'/\.svn'))
$ python compileall_exclude_dirs.py

Listing examples ...
Listing examples/.svn ...
Listing examples/.svn/prop-base ...
Listing examples/.svn/text-base ...
Compiling examples/a.py ...
Listing examples/subdir ...
Listing examples/subdir/.svn ...
Listing examples/subdir/.svn/prop-base ...
Listing examples/subdir/.svn/text-base ...
Compiling examples/subdir/b.py ...

The maxlevels argument controls the depth of recursion. For example, to avoid recursion entirely pass 0.

import compileall
import re compileall.compile_dir('examples',
maxlevels=0,
rx=re.compile(r'/\.svn'))
$ python compileall_recursion_depth.py

Listing examples ...
Compiling examples/a.py ...
 

随机推荐

  1. kattle 发送post请求

    一.简介 kattle是一款国外开源的ETL工具,纯java编写,可以在Window.Linux.Unix上运行,数据抽取高效稳定.它允许你管理来自不同数据库的数据,通过提供一个图形化的用户环境来描述 ...

  2. 理解cookie的path和domain属性

    今天在做验证码时发现一个问题:A.B窗口都打开同一个页面,A先生成一个验证码,B再生成验证码,这时A所生成的验证码被B覆盖掉了.原因是使用了同名的cookie来存储验证码.一时找不到解决方法就参考了W ...

  3. XML约束——DTD约束

    参考: 方立勋老师的讲课视频.   什么是XML约束 •在XML技术里,可以编写一个文档来约束一个XML文档的书写规范,这称之为XML约束. 为什么需要XML约束 常用的约束技术 •XML DTD • ...

  4. PB中无法插入ole控件,解决办法

    cmd /c for %i in (%windir%\system32\*.ocx) do regsvr32.exe /s %icmd /c for %i in (%windir%\system32\ ...

  5. 【Stage3D学习笔记续】山寨Starling(六):动画实现和测试

    我发布了一个版本v0.2,该版本是未优化版本,且没有添加Touch事件体系,但是由于是最基础且未优化的,所以可以通过参考代码快速的了解实现原理. 接下来的一段笔记开始进行渲染优化,我会把所有的目光都集 ...

  6. Nodejs and json

    http://cnodejs.org/topic/51bbe16960af11cd33304b75 http://www.cnblogs.com/nano/archive/2012/05/09/249 ...

  7. jQeury学习笔记

    jQuery 语法: 核心语法: $(selector).action() 美元符号定义 jQuery 选择符(selector)"查询"和"查找" HTML ...

  8. POJ 2676 Sudoku(深搜)

    Sudoku Time Limit : 4000/2000ms (Java/Other)   Memory Limit : 131072/65536K (Java/Other) Total Submi ...

  9. centos7下部署Django(nginx+uwsgi+python3+django)

    系统版本 centos7 python版本 使用官方python3.6.3正式版 django版本 使用本文发布时最新的1.11.7 uwsgi版本 使用本文发布时最新的2.0.15 nginx版本 ...

  10. zookeeper基本概念

    1.集群角色 Leader,Follower,Observer Leader服务器是整个zookeeper集群工作机制中的核心 Follower服务器是zookeeper集群状态的跟随者 Observ ...