3. Tutorials

In this tutorials, all the examples are based on this folder structure:

project/src/
    ├── foo.py
    ├── fibo.py
    ├── jsontool.py
    └── tomjson/
        ├── __init__.py
        ├── encoder.py
        ├── decoder.py
        └── scanner.py

Unless specified, the default directory in this tutorial is:

$ cd project/src/

3.1. Install & Register Pyarmor

Pyarmor is published in PyPI, install it by pip:

$ pip install pyarmor.cli

Some features need purchase Pyarmor license which could unlock RFT mode

3.2. Generate RFT Script

How to generate RFT Script for one simple script foo.py?

First create one project which only include one script foo.py:

$ pyarmor init -e foo.py

Then build this project with target --rft:

$ pyarmor build --rst

It will generate final script in the default path dist, check it:

$ cat dist/foo.py

Run it:

$ python dist/foo.py

3.3. Generate Complex RFT Script

For simple script, it’s enough by default options. But for complex scripts, it need extra options

Let’s take another script fibo.py. First create one project for it also:

$ pyarmor init --clean -e fibo.py

When building the project, there are warnings:

$ pyarmor build --rft

WARNING There are variables of unknown type
WARNING There are function calls which may use unknown arguments

It will raise exception when executing the output script:

$ python dist/fibo.py

AttributeError: 'pyarmor__7' object has no attribute 'run'

Pyarmor also supports auto-fix mode to make it works by simple and rough way:

$ pyarmor build --autofix 1

After that, build the project and test it again:

$ pyarmor build --rft
$ python dist/fibo.py

If need disable auto-fix mode, run this command:

$ pyarmor build --autofix 0

Then build project again:

$ pyarmor build --rft

3.4. Generate Mini Script

First install package pyarmor.mini:

$ pip install pyarmor.mini

We will still use the project created in the previous example and generate Mini Script with the same configuration:

$ pyarmor build --mini

Check the obfuscated script:

$ cat dist/fibo.py

Run it:

$ python dist/fibo.py

Mini Script is almost same as .pyc file in irreversibility. So usually it’s better to combine Mini Script and RFT Script by the following command:

$ pyarmor build --mini-rft

Generally, first generate RFT Script and make it works, then call above command to generate combined script.

3.5. Publish Mini Script

When publishing Mini Script, it need package pyarmor.mini too.

Or install package pyarmor.mini in the target machine:

$ pip install pyarmor.mini

Note that now only the following platforms support Mini Script

  • linux.x86_64, darwin.x86_64, windows.x86_64

  • linux.aarch64, darwin.arm64

3.5.1. Support Freethreading

Mini Script supports freethreading in Python 3.13+

Just using free-threaded Python interpreter to install package pyarmor.mini, for example:

$ python3.13t -m pip install pyarmor.mini

Make sure pip >=24.1, it will install free-threaded extension pyarmor_minit with suffix t, the installed wheel tag includes cp3.13t

3.6. Refactor Package

First create one project with package tomjson:

$ pyarmor init --clean -p tomjson

Because the package will be imported by outer scripts, the exported classes and functions can’t be renamed

In order to keep these names, one way is to enable option export_mode:

$ pyarmor env -p set rft:export_mode 1

Thus all the names list in the module attribute __all__ aren’t changed, and

  • If this is one class, no rename all the attributes and methods

  • If this is one function, no rename function arguments

Then build this package:

$ pyarmor build --rft

3.7. Create Complex Project

Let’s create one comple project, include one script jsontool.py and package tomjson, but no fibo.py and path venv:

$ pyarmor init --clean --src . -r --exclude fibo.py --exclude venv

Pyarmor will search all the files and paths in the --src, all of them except in the excludes will be added into the project.

Check the project items:

$ pyarmor build --list

Refactor this project:

$ pyarmor build --rft

Run the final script:

$ python dist/jsontool.py

3.8. Advanced Refactor

The major problem for complex scripts is to raise AttributeError. For example:

AttributeError: 'pyarmor__7' object has no attribute 'run'

Let’s look at one example script fibo.py, there are the following lines:

def fib(obj, n):
    obj.name = 'fibo'
    obj.value = n
    obj.run()
    return obj.result

The problem is that the argument obj type is unknown.

The simple way to fix this issue is to exclude these attributes. For example:

$ pyarmor env -p push rft:exclude_names name value run

The second way is annotation by updating script. For example:

def fib(obj: QuickFibo, n):
    obj.name = 'fibo'
    obj.value = n
    obj.run()
    return obj.result

The third way is to set rules to rename the attributes. For examle, this rule tell Pyarmor to rename all the attributes of obj which in the module fibo and function fib:

$ pyarmor env -p push rft:attr_rules "fibo::fib:obj.*"