V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
推荐学习书目
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 · Jul 21, 2020 · 3638 views
    This topic created in 2108 days ago, the information mentioned may be changed or developed.
    我有一个需求哦,想在包内中的一个模块隐藏一个函数,包中的__init__设置了__all__列表,然后呢,在那个模块内也写了__all__列表,但是外部 Python 文件还是可以调用到没写入__all__列表的函数,请问怎么解决这个问题呢?
    15 replies    2020-07-22 15:28:10 +08:00
    est
        1
    est  
       Jul 21, 2020 via Android
    把函数 inline 到其他函数里
    SingeeKing
        2
    SingeeKing  
    PRO
       Jul 21, 2020   ❤️ 1
    理论上动态语言做不到,不过如果实在有需求就用装饰器 + 反射验证调用来源吧
    GTD
        3
    GTD  
    OP
       Jul 21, 2020
    @est #1 请问是什么意思?没理解诶。比如我现在有一个 A 模块隶属于一个包,然后在 a 模块里面做了 all 限制,但是外部函数通过 import 整个包,还是可以调用到 a 模块里面的其他函数
    Acoolda
        4
    Acoolda  
       Jul 21, 2020 via Android   ❤️ 1
    好像是没有办法解决,无论怎么样都可以有办法调用到,只能做规则约束(就像 python 私有函数一样,下划线起头告诉其他人这是私有的)
    GTD
        5
    GTD  
    OP
       Jul 21, 2020
    @Acoolda #4 好的谢谢。但是为啥如果单独在一个模块里(那个模块不输入任何包,直接调用模块)就调用不到呢?
    MoYi123
        6
    MoYi123  
       Jul 21, 2020
    inspect 模块可以看的函数的调用栈,如果上一级调用栈不是本模块的函数,就报错。
    BingoXuan
        7
    BingoXuan  
       Jul 21, 2020   ❤️ 1
    闭包——在函数内定义函数并返回该函数,具体参考装饰器
    Leigg
        8
    Leigg  
       Jul 21, 2020 via Android   ❤️ 1
    __call__了解一下
    poet00
        9
    poet00  
       Jul 21, 2020   ❤️ 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  
       Jul 21, 2020
    把这个函数嵌套到某个函数里面。

    还可以用字符串定义函数,然后 exec 加载
    leimao
        11
    leimao  
       Jul 21, 2020
    Python 我记得你怎么做都能破解。所以不建议隐藏,没意义。
    llsquaer
        12
    llsquaer  
       Jul 22, 2020
    转为 pyd?
    no1xsyzy
        13
    no1xsyzy  
       Jul 22, 2020
    @kxiaong #9 那么你还得想办法藏起这个 fun_prefix,避免被反射(准确地叫内省)拿出来。
    no1xsyzy
        14
    no1xsyzy  
       Jul 22, 2020
    真要搞没办法的,甚至可以写个 C extension 甚至魔改的 Python 实现,以允许遍历全部对象、全部 frame,甚至直接动 AST,顺便干扰 inspect 模块的调用,避免你再回头检测调用者。
    唯一的 solution 就是不写成 Python 代码。
    sikong31
        15
    sikong31  
       Jul 22, 2020
    可以用 del 删除
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   5426 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 57ms · UTC 08:11 · PVG 16:11 · LAX 01:11 · JFK 04:11
    ♥ Do have faith in what you're doing.