如何"假"一个模块安全地放在Python包中

时间:2015-02-16 23:01:24

标签: python git packages setuptools

目前,我在主git分支中有以下目录结构:

/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的{​​{1}},至少对于70%的代码(我必须手动更新module1.py)。那么有更好的方法来解决这个问题吗?

  2. 为了保持API的一致性,我希望使用我的软件包旧版本的人仍然使用module2.pyfrom dir1.module import abc中没有module.py)这可以做到就像描述here一样,但这会带来弄乱dir1路径变量的危险,但不建议考虑稳定性和安全性。有没有更好的方法可以使API向后兼容并且仍然安全/稳定?


  3. 然而,我的情况更复杂。有关更具代表性的示例,请考虑从:

    移动
    sys

    为:

    /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.py的不同功能,并将它们重新组合为单独的dir1/module_3.pymodule_add.py,并将其置于module_sub.py之下

    但是,获得版本2程序包的版本1用户仍然可以执行:

    /dir1/dir2

    我不能做的事情:

    • from module_2 import add2, sub2 from module_3 import add3 中有module_2.pymodule_3.py(我需要git来关联和跟踪我的分支的主分支dir1dir1/module_2.py;
    • 以任何降低稳定性/安全性的方式改变或弄乱dir1/dir2/module_2.py;或
    • sys.path重命名为例如dir2

1 个答案:

答案 0 :(得分:4)

请注意以下设置:

/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)

__init__.py/dir1/module_2中的/dir1/module_3文件,向用户发出警告,告知这些导入现在正在进行中。例如:

>>> 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