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