Python 如何在包内的某一个模块隐藏某一个函数呢? - V2EX
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 3395 次点击
    这是一个创建于 1920 天前的主题,其中的信息可能已经有所发展或是发生改变。
    我有一个需求哦,想在包内中的一个模块隐藏一个函数,包中的__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  
    PRO
       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     Solana     2677 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 33ms UTC 14:56 PVG 22:56 LAX 07:56 JFK 10:56
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86