【问题标题】:How to "fake" a module safely in a Python package如何在 Python 包中安全地“伪造”模块
【发布时间】:2015-04-17 13:53:17
【问题描述】:

目前我在mastergit分支中有如下目录结构:

/dir1
    __init__.py
    module.py

这将更改为(在我的分支中):

/dir1
    __init__.py
    /dir2
        module1.py # With 70% of code of module.py
        module2.py # With 30% of code of module.py

问题:

  1. 我知道不可能让git 跟踪两个新文件,但由于git 识别重命名(并且它认为将文件夹组织为重命名)我将能够跟踪对module.py 的更改master 分支到我的分支的module1.py,至少对于 70% 的代码(我必须手动更新module2.py)。那么有没有更好的办法来处理呢?

  2. 1234563但这会带来与sys 路径变量混淆的危险,出于稳定性和安全性考虑,不建议这样做。有没有更好的方法可以使 API 向后兼容并且仍然安全/稳定?

但是,我的情况比较复杂。对于更具代表性的示例,请考虑从:

/dir1
    __init__.py
    module_2.py
        def add2(a, b):
            return a + b
        def sub2(a, b):
            return a - b
    module_3.py
        def add3(a, b, c):
            return a + b + c

到:

/dir1
    __init__.py
    /dir2
        __init__.py
        module_add.py
            # ... Constitutes 70% of code from `dir1/module_2.py`
            def add2(a, b):
                return a + b
            # A few more additional lines added from `dir1/module_3.py`
            def add3(a, b, c):
                return a + b + c
        module_sub.py
            # Constitutes the 30% from /dir1/module2.py
            def sub2(a, b):
                return a - b

所以本质上,我将dir1/module_2.pydir1/module_3.py 的不同功能分开,并将它们重新组合成单​​独的module_add.pymodule_sub.py,并将其放在/dir1/dir2

但是,获得版本 2 软件包的版本 1 用户应该仍然可以这样做:

from module_2 import add2, sub2
from module_3 import add3

我不能做的事:

  • dir1 中有module_2.pymodule_3.py(我需要git 来关联和跟踪主分支的dir1/module_2.py 到我的分支的dir1/dir2/module_2.py);
  • 以任何会降低稳定性/安全性的方式更改或弄乱sys.path;或
  • dir2 重命名为例如module_2

【问题讨论】:

  • 你真的需要避免module.py吗?你可以只创建一个module.py 来实现from dir2.module1 import *from dir2.module2 import *
  • @BrenBarn 这是当前设置... :) 没有定义 module.py 可以帮助我跟踪更改(至少 70%)到 modue.py 在我的分支的 dir2/module1.py.. .
  • @jonrsharpe 破坏了 API 的向后兼容性;)
  • 如果以前他们这样做 from dir1.module import abc 我不希望他们现在这样做 from dir1.dir2.module1 import abc from dir1 import abc...我需要这个的原因是,工作是针对维护良好且广泛使用的开源包...它需要至少 2 个发布周期来强制用户执行from dir1.dir2.module1 import abcfrom dir1 import abc...所以需要一种干净的方法来保持它向后兼容。 ..(为了我/其他开发人员的方便,可以通过 git 跟踪)
  • 啊,太聪明了;) 真的很抱歉,结构有点复杂,dir2 是几个这样的module-s 的集合...感谢您的耐心回复 :)

标签: python git packages setuptools


【解决方案1】:

注意以下设置:

/dir1
    __init__.py
        from module import abc
    module.py
        abc = None

从外部(几乎)无法区分:

/dir1
    __init__.py
        from module import abc
    /module
        __init__.py
           from module1 import abc
        module1.py  # this is the moved and renamed module.py, with git history
            abc = None
        module2.py  # this is the 30% you've factored out
            # whatever's in here

外部module.py/module,旧的导入from module import abc(和from dir1.module import abc等)继续工作。


对于您更复杂的示例,您仍然可以从以下位置切换:

/dir1
    __init__.py
        from module_2 import add2, sub2
        from module_3 import add3
    module_2.py
    module_3.py

到:

/dir1
    __init__.py
        from dir2.module_add import add2, add3
        from dir2.module_sub import sub2
    /dir2
        __init__.py
        module_add.py  # module_2.py moved & renamed
        module_sub.py  # module_3.py moved & renamed or new file
    /module_2
        __init__.py
           from ..dir2.module_add import add2
           from ..dir2.module_sub import sub2
    /module_3
        __init__.py
           from ..dir2.module_add import add3

旧代码(例如from dir1.module_2 import add2)仍然可以正常工作,但用户现在可以开始访问新位置(例如from dir1.dir2.module_add import add2, add3)。


您也可以添加例如:

import warnings
warnings.warn("deprecated", DeprecationWarning)

/dir1/module_2/dir1/module_3 中的__init__.py 文件,向用户提供这些导入即将结束的警告。例如:

>>> import warnings
>>> warnings.simplefilter('always')
>>> from dir1.dir2.module_sub import sub2
>>> sub2(1, 2)
-1
>>> from dir1.module_3 import add3

Warning (from warnings module):
  File "dir1\module_3\__init__.py", line 2
    warnings.warn("deprecated", DeprecationWarning)
DeprecationWarning: deprecated
>>> add3(1, 2, 3)
6

【讨论】:

    猜你喜欢
    • 2015-11-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-12
    • 2017-01-21
    • 1970-01-01
    • 2017-06-07
    • 1970-01-01
    • 2015-10-05
    相关资源
    最近更新 更多