Q:为什么要对python脚本保护?
A:虽然自己代码写的菜,但是确实不想暴露源代码。

方案一 删除内置函数

dir可以用来查看参数的属性、方法列表,即使你用pyinstaller打包了脚本,但其他人依然可以在import后用它查看你的函数方法等。
如果把这个函数删除则可以避免这个问题。

脚本1:

import builtins
delattr(builtins, "dir")
class T:
    def a(self):
        print("is a.")

脚本2:

from script1 import T
t = T()
t.a()
print(dir(t))

脚本2输出:

is a.
Traceback (most recent call last):
  File "script1.py", line 10, in <module>
    print(dir(t))
NameError: name 'dir' is not defined

方案二 判断调用来源函数名

主要用到inspect这个库

脚本1:

from inspect import getouterframes, currentframe

class T:
    def a(self):
        callname = getouterframes(currentframe(), 2)[1][3]
        if callname != "callreal":
            print("You are idiot!")
        else:
            print("is a.")

脚本2:

from script1 import T

t = T()

def calltest():
    t.a()

def callreal():
    t.a()

if __name__ == "__main__":
    calltest()
    callreal()

脚本2输出:

You are idiot!
is a.

方案三 修改内置函数

继承——修改——覆盖

oldList = list
class NewList(list):
    def __len__(self):
        raise AttributeError("禁止使用!")
list = NewList
q = list()
print(q.__len__())

输出:

Traceback (most recent call last):
  File "script2.py", line 13, in <module>
    print(q.__len__())
  File "script2.py", line 10, in __len__
    raise AttributeError("禁止使用!")
AttributeError: 禁止使用!

方案四 对类中的函数重写为自己的逻辑

示例:

class B(type):
    def __getattribute__(self, name):
        if name == "__dict__" or name == "__bases__":
            return {"禁偷窥":""}
        return super().__getattribute__(name)

class A(metaclass=B):
    def a(self):
        print("a")

    def b(self):
        print("b")

t = A()
t.a()
t.b()

print(dir(A))
print("a" in dir(A))
print("b" in dir(A))

输出:

a
b
['禁偷窥']
False
False

标签: none

添加新评论