Python 如何在包内的某一个模块隐藏某一个函数呢?

2020-07-21 11:06:26 +08:00
 GTD
我有一个需求哦,想在包内中的一个模块隐藏一个函数,包中的__init__设置了__all__列表,然后呢,在那个模块内也写了__all__列表,但是外部 Python 文件还是可以调用到没写入__all__列表的函数,请问怎么解决这个问题呢?
3084 次点击
所在节点    Python
15 条回复
est
2020-07-21 11:09:51 +08:00
把函数 inline 到其他函数里
SingeeKing
2020-07-21 11:12:27 +08:00
理论上动态语言做不到,不过如果实在有需求就用装饰器 + 反射验证调用来源吧
GTD
2020-07-21 11:13:32 +08:00
@est #1 请问是什么意思?没理解诶。比如我现在有一个 A 模块隶属于一个包,然后在 a 模块里面做了 all 限制,但是外部函数通过 import 整个包,还是可以调用到 a 模块里面的其他函数
Acoolda
2020-07-21 11:40:28 +08:00
好像是没有办法解决,无论怎么样都可以有办法调用到,只能做规则约束(就像 python 私有函数一样,下划线起头告诉其他人这是私有的)
GTD
2020-07-21 12:03:33 +08:00
@Acoolda #4 好的谢谢。但是为啥如果单独在一个模块里(那个模块不输入任何包,直接调用模块)就调用不到呢?
MoYi123
2020-07-21 12:07:45 +08:00
inspect 模块可以看的函数的调用栈,如果上一级调用栈不是本模块的函数,就报错。
BingoXuan
2020-07-21 12:22:58 +08:00
闭包——在函数内定义函数并返回该函数,具体参考装饰器
Leigg
2020-07-21 12:34:27 +08:00
__call__了解一下
kxiaong
2020-07-21 13:20:24 +08:00
如果是 module 一级的函数,理论上是不可能的。
类中封装的函数可以使用双下划线开头,使方法变成私有方法。module 一级的方法事实上跟包中定义的 class 是同一级别,而 python 对包一级的对象和函数,只有约定俗成的访问控制,而非强制。

我猜想一个可能比较 dirty 的方法:

使用一个字符串、时间戳与一个枚举的随机数做 md5,产生的结果作为一个私有函数的前缀,比如:
`fun_prefix = hashlib.md5(encryptStr + str(time.time() )+ str(randInt) ).hexdigit()`

你的私有函数名字可以是: `fun_prefix+"my_private_function"`.

然后你在程序中调用时使用反射来调用函数。
因为外部不太可能知道你产生 fun_prefix 时的混淆算法,因此外部每次加载你的包时,看到的都是一个随机字符串+“my_private_function”的函数名,因此也没法调用你的函数。

如果你不得不用源代码的方式发布,可以把混淆加密部分做成二进制跟随你的包一起发布。
ruanimal
2020-07-21 15:14:06 +08:00
把这个函数嵌套到某个函数里面。

还可以用字符串定义函数,然后 exec 加载
leimao
2020-07-21 15:15:42 +08:00
Python 我记得你怎么做都能破解。所以不建议隐藏,没意义。
llsquaer
2020-07-22 10:35:28 +08:00
转为 pyd?
no1xsyzy
2020-07-22 10:43:55 +08:00
@kxiaong #9 那么你还得想办法藏起这个 fun_prefix,避免被反射(准确地叫内省)拿出来。
no1xsyzy
2020-07-22 10:51:25 +08:00
真要搞没办法的,甚至可以写个 C extension 甚至魔改的 Python 实现,以允许遍历全部对象、全部 frame,甚至直接动 AST,顺便干扰 inspect 模块的调用,避免你再回头检测调用者。
唯一的 solution 就是不写成 Python 代码。
sikong31
2020-07-22 15:28:10 +08:00
可以用 del 删除

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/691833

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX