我最近被要求在工作中将代码从一个子包移动到另一个子包,而我使用的方法对其他开发人员来说似乎并不明显,所以我在这里为其他人记录它。
我不建议在旧地方留下副本。如果您有相同脚本的两份副本,则一份可能会在没有另一份的情况下更改。相反,我推荐以下多步骤过程。
如果您控制代码的两个位置,则第一步涉及可以同时实现的两个部分。
第一步:实施行动
首先,将文件从旧位置移动到版本控制下的新位置。我使用 CVS 的简化界面,所以它是一个版本控制副本。在大多数其他版本控制系统(如 mercurial、subversion 和 git)中,您应该使用mv
来移动文件,例如使用 git:
git mv /location/old/script.py /location/new/script.py
重要的:
__init__.py
不要忘记移动单元测试,如果需要保留旧代码中的代码,也要移动's。__init__.py
否则,如果它们还没有到位,请确保 commit 's 在那里
接下来,在旧代码的位置,从新位置导入所有名称,
所以在/location/old/script.py
:
from location.new.script import *
并留下评论解释为什么需要这样做,并将更改提交给版本控制。如果您移动了__init__.py
,只需确保提交一个新的空__init__.py
。
这里有一个重要的警告。import *
受 影响__all__
。如果你有一个__all__
声明,你有两种方法来提供缺失的名字。您可以显式导入它们:
from location.new.script import *
# names not in the new.script's __all__:
from location.new.script import foo, bar, baz
或者您可以删除该文件并改为在 中导入模块__init__.py
,然后将路径添加到 sys.modules 中,如下所示:
from location.new import script
import sys
sys.modules['location.old.script'] = script
此代码将初始化包并sys.modules
及时添加模块,以便导入器在那里查找它。这与在Python 源代码os.path
中创建的方式相同。但是,大多数人会回避修改. 事实上,我很犹豫把这个建议留在这里,如果它不在 Python 标准库中,我也不会。sys.modules
这两个部分可以一起投入生产,并且这一举措已经无缝实施。如果您无法控制代码的用户,则可能需要无限期地保留该代码以实现向后兼容性。
可选:然后我会删除开头的旧脚本(就在开头,不要推送它!),以便其他开发人员可以看到即将发生的更改并及时解决更改。
第二步:实现引用
如果您可以对依赖于您的代码的所有代码进行正则表达式搜索,我建议您在代码中搜索以下正则表达式:
(import|from).*location\.old.*script
如果您在 Unix 上(或有 Cygwin),您可以对其进行正则表达式搜索:
grep -rEe "(import|from).*location\.old.*script" .
或者大多数 IDE 都有正则表达式搜索。
如果您确实可以控制使用它的代码,或者您对使用它的其他人有看法,那么将导入从旧的更改为新的相当简单,例如从:
import location.old.script
到
import location.new.script
并从
from location.old import script
到
from location.new import script
等等。
重要的:
所有这些更改都需要实施并发布到生产环境中。如果任何生产安装仍未完成,如果您删除旧位置,它们将失败。
第三步:删除生产中的旧脚本
这是危险的一步。如果您错过了任何用户/进口商,他们的代码将失败,直到他们将进口修复程序投入生产。您可以选择无限期推迟此步骤,但如果我能证明所有更改都已投入生产,我更愿意及时完成。
如果您在进行更改后立即将其删除,以便其他人可以看到正在开发中的更改,您可能不必担心。
不过,在您可以证明没有其他用户在生产中引用旧包位置之前,请不要删除它。如果你不能证明它,不要删除它。