V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
GTD
V2EX  ›  Python

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

  •  
  •   GTD · 2020-07-21 11:06:26 +08:00 · 3086 次点击
    这是一个创建于 1578 天前的主题,其中的信息可能已经有所发展或是发生改变。
    我有一个需求哦,想在包内中的一个模块隐藏一个函数,包中的__init__设置了__all__列表,然后呢,在那个模块内也写了__all__列表,但是外部 Python 文件还是可以调用到没写入__all__列表的函数,请问怎么解决这个问题呢?
    15 条回复    2020-07-22 15:28:10 +08:00
    est
        1
    est  
       2020-07-21 11:09:51 +08:00 via Android
    把函数 inline 到其他函数里
    SingeeKing
        2
    SingeeKing  
       2020-07-21 11:12:27 +08:00   ❤️ 1
    理论上动态语言做不到,不过如果实在有需求就用装饰器 + 反射验证调用来源吧
    GTD
        3
    GTD  
    OP
       2020-07-21 11:13:32 +08:00
    @est #1 请问是什么意思?没理解诶。比如我现在有一个 A 模块隶属于一个包,然后在 a 模块里面做了 all 限制,但是外部函数通过 import 整个包,还是可以调用到 a 模块里面的其他函数
    Acoolda
        4
    Acoolda  
       2020-07-21 11:40:28 +08:00 via Android   ❤️ 1
    好像是没有办法解决,无论怎么样都可以有办法调用到,只能做规则约束(就像 python 私有函数一样,下划线起头告诉其他人这是私有的)
    GTD
        5
    GTD  
    OP
       2020-07-21 12:03:33 +08:00
    @Acoolda #4 好的谢谢。但是为啥如果单独在一个模块里(那个模块不输入任何包,直接调用模块)就调用不到呢?
    MoYi123
        6
    MoYi123  
       2020-07-21 12:07:45 +08:00
    inspect 模块可以看的函数的调用栈,如果上一级调用栈不是本模块的函数,就报错。
    BingoXuan
        7
    BingoXuan  
       2020-07-21 12:22:58 +08:00   ❤️ 1
    闭包——在函数内定义函数并返回该函数,具体参考装饰器
    Leigg
        8
    Leigg  
       2020-07-21 12:34:27 +08:00 via Android   ❤️ 1
    __call__了解一下
    kxiaong
        9
    kxiaong  
       2020-07-21 13:20:24 +08:00   ❤️ 1
    如果是 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
        10
    ruanimal  
       2020-07-21 15:14:06 +08:00
    把这个函数嵌套到某个函数里面。

    还可以用字符串定义函数,然后 exec 加载
    leimao
        11
    leimao  
       2020-07-21 15:15:42 +08:00
    Python 我记得你怎么做都能破解。所以不建议隐藏,没意义。
    llsquaer
        12
    llsquaer  
       2020-07-22 10:35:28 +08:00
    转为 pyd?
    no1xsyzy
        13
    no1xsyzy  
       2020-07-22 10:43:55 +08:00
    @kxiaong #9 那么你还得想办法藏起这个 fun_prefix,避免被反射(准确地叫内省)拿出来。
    no1xsyzy
        14
    no1xsyzy  
       2020-07-22 10:51:25 +08:00
    真要搞没办法的,甚至可以写个 C extension 甚至魔改的 Python 实现,以允许遍历全部对象、全部 frame,甚至直接动 AST,顺便干扰 inspect 模块的调用,避免你再回头检测调用者。
    唯一的 solution 就是不写成 Python 代码。
    sikong31
        15
    sikong31  
       2020-07-22 15:28:10 +08:00
    可以用 del 删除
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1105 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 106ms · UTC 19:12 · PVG 03:12 · LAX 11:12 · JFK 14:12
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.