3.6. 常见的使用错误

在 Pyarmor 开发组处理的报告中,有 80% 属于使用错误的问题,根据用户这些常见的错误问题,Pyarmor 开发组整理该文档。请首先通过该文档的检查确认不是使用错误,对于使用错误的问题,这里也会提示出正确的使用方法。

如果是加密过程发生的错误,请查看章节 运行 Pyarmor 的设备 并根据相应的条件查找解决方案

如果是运行加密过程发生的错误,请查看章节 运行加密脚本的设备 根据相应的条件查找解决方案

3.6.1. 运行 Pyarmor 的设备

3.6.1.1. 启动失败

  1. 检查是否已经正确安装 pyarmor.cli.core 包

    搜索 pyarmor 的安装目录树中是否存在扩展模块 pytransform3.pyd 或者 pytransform3.so

    如果不存在,请参考安装文档进行正确安装

  2. 检查扩展模块 pytransform3 是否适用于当前平台

    使用 Python 直接运行下面的命令:

    $ python
    >>> from pyarmor.cli.core import Pytransform3
    >>> Pytransform3.version()
    1
    >>>
    

    如果不能正确返回,尝试使用下面的命令检查扩展模块是否适用于当前平台

    在 Linux 平台下面,使用 ldd 执行下面的命令

    $ ldd /path/to/pytransform3.so
    

    在 MacOS 平台下面,使用 codesign 和 otool 执行下面的命令

    $ codesign -v /path/to/pytransform3.so
    $ otool -L /path/to/pytransform3.so
    

    在 Windows 平台下面,使用 [cygcheck] 进行检查:

    C:\> cygcheck \path\to\pytransform3.pyd
    

    或者:

    C:\> dumpbin /dependents \path\to\pytransform3.pyd
    

    根据报错信息安装相应的包看能否解决问题

  3. 如果上面的命令报错并且无法解决,查看 生成加密脚本的环境 是否支持当前平台

    对于 Linux 的变体系统,可以查看包 pyarmor.cli.core.linux , pyarmor.cli.core.alpine ,以及 pyarmor.cli.core.android 等的内容,每一个包里面都有多个 pytransform.so ,例如:

    $ unzip ./pyarmor.cli.core.linux-6.5.3-cp310-none-any.whl
    
    Archive:  ./pyarmor.cli.core.linux-6.5.3-cp310-none-any.whl
      inflating: pyarmor/cli/core/linux/__init__.py
      inflating: pyarmor/cli/core/linux/aarch64/pyarmor_runtime.so
      inflating: pyarmor/cli/core/linux/aarch64/pytransform3.so
      inflating: pyarmor/cli/core/linux/armv7/pyarmor_runtime.so
      inflating: pyarmor/cli/core/linux/armv7/pytransform3.so
      inflating: pyarmor/cli/core/linux/loongarch64/pyarmor_runtime.so
      inflating: pyarmor/cli/core/linux/loongarch64/pytransform3.so
      inflating: pyarmor/cli/core/linux/mips32el/pyarmor_runtime.so
      inflating: pyarmor/cli/core/linux/mips32el/pytransform3.so
      ...
    

    依次使用 ldd 检查,如果某一个包中某一个目录下面的 pytransfrom.so 可以用,那么拷贝它们到包 pyarmor.cli.core 的安装目录,例如:

    $ cp pyarmor/cli/core/linux/loongarch64/*.so /path/to/pyarmor/cli/core
    $ pyarmor gen foo.py
    

    或者安装这个包,同时设置环境变量:

    $ pip install ./pyarmor.cli.core.linux-6.5.3-cp310-none-any.whl
    $ export PYARMOR_PLATFORM=linux.loongarch64
    $ pyarmor gen foo.py
    
  4. 如果支持该平台,那么尝试升级 Python 小版本到最新的补丁版本,例如,升级 Python 3.11.0b2 到 3.11.9

3.6.1.2. 注册失败

如果使用的是 激活文件 ( pyarmor-regcode-xxxx.txt ),确保使用次数没有超过 3 次,正常情况下这个文件仅用于第一次激活注册,以后的所有注册都应该使用 注册文件 pyarmor-regfile-xxxx.zip

invalid activation file

如果注册的时候抛出这种异常,请确认该注册文件满足下列条件:

  • 这个文本文件是 Pyarmor 开发组发送的激活邮件的附件,并且该附件没有被邮件系统进行篡改

  • 这个文本文件的内容开始必须是 Dear ... ,并且包含一个激活码,该激活码必须是单独一行,不能分为多行

基础版或者专家版许可证

  1. 检查设备的日期时间设置是否正确

  2. 是否一分钟之内运行超过 3 次的注册命令

  3. 如果是在运行 Docker 容器的话,是否在一分钟之内运行超过 3 个的 Docker 容器

  4. 是否在 24 小时之内在超过 100 台不同设备(Docker 容器)上面运行注册命令

如果以上限制都没有超过的话,

  1. 尝试在浏览器访问 http://pyarmor.dashingsoft.com/api/auth2/ 或者直接使用 curl 等进行测试

    如果返回 "NO:missing parameters" ,这说明网络和 Pyarmor 服务器都是好着的

    否则请检查本机的网络配置

  2. 检查 Python 解释器是否可以访问 Pyarmor 服务器。使用 Python 解释器执行下面的命令,如果无法返回期望结果,那么请检查本机防火墙配置或者公司网络配置

    $ python
    >>> from urllib.request import urlopen
    >>> res = urlopen('http://pyarmor.dashingsoft.com/api/auth2/')
    >>> print(res.read())
    b'NO:missing parameter'
    

    注意如果当前设备安装有多个 Python 的话,这个 Python 解释器必须是用来执行 Pyarmor 的解释器,否则没有意义

  3. 如果以上都正确返回,还是无法注册成功,请提交问题报告

    报告中需要包含注册失败的许可证编号,例如 pyarmor-vax-6058

集团版许可证

  1. 当前设备的 Machine ID 是否每次启动发生变化

    • 如果使用的是 Pyarmor 8.5 之前的版本,首先升级 Pyarmor 到最新版本

    • 如果是在硬件信息重启之后会发生变化的虚拟机器,例如 Github Action 的默认 runner ,无法直接使用集团版许可证

  2. 是否已经使用集团版许可证的 注册文件 (一般为 pyarmor-regfile-????.zip )生成了当前设备的注册文件(一般为 pyarmor-device-regfile-????.N.zip )

  3. 设备注册文件中的 Machine ID 是否和当前设备匹配

  4. 如果设备 Machine ID 每次启动都保持不变,并且使用了正确的设备注册文件,请提交问题报告,至少包含下列信息:

    • 设备的 Machine ID

    • 设备类型,是物理设备,还是虚拟机,还是云服务器等

    • 操作系统类型

    • 对于类似 Linux 系统,提供 uname -a 的输出

使用集团版许可证运行多个本地 Docker 容器

  1. 确保 Docker 主机 和 Docker 容器在同一个网络中,使用 ifconfig 命令检查网路配置。

    在 Docker 容器,检查注册命令的控制台输出。例如:

    $ pyarmor reg ./pyarmor-device-regfile-xxxx.1.zip
    
    INFO     Python 3.12.12
    INFO     Pyarmor 9.1.8 (trial), 000000, non-profits
    INFO     Platform linux.x86_64
    INFO     register "./pyarmor-device-regfile-xxxx.1.zip"
    INFO     machine id in group license: m5532894dc5ccf82a061382a3ffbb0af00af
    INFO     no machine id matchs this group license
    INFO     take this machine as docker container, and connect to docker host
    for authentication...
    INFO     socket addr: ('192.168.139.57', 39044)
    INFO     remote addr: ('192.168.139.3', 29092)
    ...
    

    最重要的是 socket addr 和 remote addr ,请确保它们在同一个网络,并且 netmask 是相同的

  2. 检查客户端到认证服务器的网络路由,hops 不能超过 2

    在 Docker 容器,使用 traceroute 或者类似命令查看。继续上面的例子:

    $ traceroute host.docker.internal
      traceroute to 192.168.139.3 (192.168.139.3), 30 hops max, 60 byte packets
      1  192.168.139.3 (192.168.139.3)  0.618 ms  0.259 ms  0.185 ms
    

    至多只能有 2 hops,否则只能认证服务器只能收到空数据包

    如果 host.docker.internal 不是 192.168.139.3 ,可以使用环境变量设置:

    $ export PYARMOR_DOCKER_HOST=192.168.139.3
    
  3. 参阅 Docker 文档,修改网络配置,确保满足上面两个条件,否则无法使用

    如果使用的 Windows Host 和 Linux Container ,参考这里的解决方案

    https://github.com/dashingsoft/pyarmor/issues/2229

  4. 如果 Docker 容器中有 /dev/disk 目录的,删除或者重命名为其它目录:

    $ sudo mv /dev/disk /dev/nodisk
    

3.6.1.3. 加密失败

update license token failed

请参考 注册失败 中的解决方案

加密出现其他异常或者错误信息

  1. 加密一个简单脚本 foo.py ,看能否成功

  2. 如果不能成功,那么参考上面 启动失败 的检查点,确保扩展模块 pytransform3 适用当前平台

  3. 如果扩展模块没有问题,请尝试在忽略配置环境产生的影响

    例如,把当前目录下面的局部配置目录 .pyarmor 更名为 .pyarmor.bak , 把全局配置目录 ~/.pyarmor/config 更名为 ~/.pyarmor/config.bak

  4. 使用更少加密选项,看能否成功,确定导致问题的选项

  5. 报告问题,使用调试选项 -d 生成 pyarmor.report.bug ,并基于此

    • 提交一个尽可能简单的可以重现的脚本

    • 加密选项使用最少的可以重现的选项,尽量不要提交不会导致崩溃的无关选项

3.6.1.4. 打包失败

  1. 直接使用 PyInstaller 打包没有加密的脚本,确保打包可以成功

  2. 查看 详解可独立运行的加密脚本

3.6.2. 运行加密脚本的设备

3.6.2.1. 导入运行辅助库装载失败

  1. 检查 运行辅助包 是否存在

    在加密脚本目录树中,搜索扩展模块 pyarmor_runtime.pyd 或者 pyarmor_runtime.so ,确保其存在

    运行辅助包 是一个正常的 Python 包,可以把它当作第三方的包来使用,但是必须能够被加密脚本导入

  2. 检查加密脚本的导入语句是否正确

    直接打开加密脚本,应该可以看到加密脚本的第一条语句是一个标准的 from ... import 语句,请按照 Python 本身的导入机制确保能导入 运行辅助包

    可以通过移动运行辅助包的位置或者修改导入语句,以及使用选项 -i 或者 --prefix 重现生成加密脚本来解决这个问题

  3. 尝试升级 Python 小版本到最新的补丁版本,例如,升级 Python 3.11.0b2 到 3.11.9

如果加密设备和目标设备不是同一台机器

  1. 确保运行加密脚本的 Python 版本和加密时候使用的 Python 大小版本(Major.Minor)一致

  2. 如果两者架构不同,请确保加密的时候使用了正确的跨平台加密选项 --platform

  3. 检查扩展模块 pyarmor_runtime 是否匹配目标设备的 Python 版本和平台架构

    在 Linux 平台下面,使用 ldd 执行下面的命令

    $ ldd /path/to/pyarmor_runtime.so
    

    在 MacOS 平台下面,使用 codesign 和 otool 执行下面的命令

    $ codesign -v /path/to/pyarmor_runtime.so
    $ otool -L /path/to/pyarmor_runtime.so
    

    在 Windows 平台下面,使用 [cygcheck] 进行检查:

    C:\> cygcheck \path\to\pyarmor_runtime.pyd
    

    或者:

    C:\> dumpbin /dependents \path\to\pyarmor_runtime.pyd
    

    根据报错信息安装相应的包看能否解决问题。

如果无法解决问题,查看 生成加密脚本的环境 是否支持当前平台

另外对于跨平台加密,尝试使用不同的目标平台,例如目标平台是 Android 的话,如果 --platform android.aarch64 加密的脚本无法运行,可以尝试 --platform linux.aarch64 或者 --platform alpine.aarch64 ,因为它们的区别主要在于使用不同的 LIBC 库

unauthorized use of script

  1. 不要使用 --private , --restrict , --assert-call , --assert-import 等约束选项

  2. 使用 pyarmor cfg assert.call:excludes "xxx" 或者 pyarmor cfg assert.import:excludes "xxx" 排除出现问题的函数和模块

  3. 发现导致出现问题的选项,并报告问题,至少包含以下内容

    • 加密时候使用的完整选项

    • 可以重现问题的简单脚本,不要使用第三方库,尤其是依赖很多,安装包很大的第三方库

    • 运行加密脚本的完整命令和完整的异常信息堆栈

3.6.2.2. 运行加密脚本出现错误或者异常

  1. 尝试不要使用 RFT/BCC/约束选项等进行加密,看是否可以运行,可以运行的话说明问题是 RFT/BCC/约束选项 造成的,请参考下面的相应分支继续检查

  2. 如果使用最少的选项加密脚本依旧不可以运行,尝试加密一个简单脚本,看看是否可以正确运行

  3. 简化脚本,尝试找到一个可以重现问题的最简单脚本,最好不需要使用第三方库,如果使用到第三方库,查看 如何解决第三方库调用加密脚本存在的问题

  4. 提交问题报告,至少包含下列内容

    • 加密时候使用的完整选项

    • 可以重现问题的简单脚本,不要使用第三方库,尤其是依赖很多,安装包很大的第三方库

    • 运行加密脚本的完整命令和完整的异常信息堆栈

使用了约束选项进行加密

参考上面的 unauthorized use of script

使用了 RFT 模式进行加密

参阅 使用 RFT 模式加密脚本 pro 中的解决方案

使用了 BCC 模式进行加密

首先使用一个简单脚本验证环境配置正确,如果简单脚本不工作,那么是多数是配置不正确或者未知的环境变量的影响

然后参阅 使用 BCC 模式加密脚本 pro 中的解决方案

3.6.2.3. 运行打包的加密脚本出现错误或者异常

  1. 不要打包,只是使用相同选项加密脚本,然后运行加密后的脚本,检查是否运行正常,如果不正常,那么参考上面加密脚本运行失败的解决方案

  2. 不要加密脚本,直接使用 PyInstaller 打包没有加密的脚本,检查打包后的可执行文件是否运行正常,如果不正常,请参考 PyInstaller 文档解决问题

  3. 如果以上都正常,尝试使用更少的加密选项,重复步骤 1 和 步骤 2,找到导致问题出现的选项,然后报告问题

特别的,如果打包设备和目标设备不是同一台机器,必须在目标设备上检查运行结果

例如,在步骤1的检查中,直接在加密设备上运行加密脚本是没有意义的,必须在目标设备上运行加密脚本进行检查

3.6.3. 平台相关问题

Darwin Apple Silicon 如果刚运行就崩溃,那么需要对扩展模块 pytransform3 或者 pyarmor_runtime 进行签名

注释

cygcheck(1,2)

如何快速获取 cygcheck.exe

直接下载 https://pyarmor.dashingsoft.com/downloads/tools/cygcheck.zip 解压

或者从官网下载

  • 打开 https://cygwin.com/mirrors.html

  • 选择一个网站,依次进入目录 x86_64/release/cygwin/

  • 下载最新的 cygwin-3.5.3-1.tar.xz

  • 解压 tar xJf cygwin-3.5.3-1.tar.xz

  • 提取其中的 cygcheck.exe