【问题标题】:Automatically deleting pyc files when corresponding py is moved (Mercurial)移动对应的 py 时自动删除 pyc 文件(Mercurial)
【发布时间】:2011-02-01 11:10:51
【问题描述】:

(3个月前我就预见到这个问题可能会发生,并被告知要努力避免它。昨天,我被它咬得很厉害,现在它花了我真钱,我很想解决它.)

如果我将一个 Python 源文件移动到另一个目录,我需要记得告诉 Mercurial 它已移动 (hg move)。

当我使用 Mercurial 将新软件部署到我的服务器时,它会小心地删除旧的 Python 文件并在新目录中创建它。

但是,Mercurial 不知道同一目录中的 pyc 文件,并将其留在后面。旧的 pyc 优先于新的 python 文件被同一目录下的其他模块使用。

随之而来的不是欢闹。

如何说服 Mercurial 在我移动 python 文件时自动删除我的旧 pyc 文件?还有其他更好的做法吗?试图记住从所有 Mercurial 存储库中删除 pyc 文件不起作用。

【问题讨论】:

    标签: python mercurial


    【解决方案1】:

    我使用这个脚本来删除当前文件夹中的.pyc文件,这个脚本可以单独使用,也可以包含在exit函数中,当你退出时删除.pyc文件。

    import os
    files = [f for f in os.listdir('.') if os.path.isfile(f) and '.pyc' in str(f)]
    for f in files : os.unlink(os.getcwd()+'/'+f)
    

    【讨论】:

      【解决方案2】:

      这是一个 unix 单行程序,每次运行 hg update 时都会删除 .pyc 文件。

      将此添加到您的 hgrc 文件中:

      [hooks]
      preupdate.cleanpyc = hg status --no-status --removed --deleted --include "**.py" --rev .:$HG_PARENT1 --print0 | xargs -0 -I '{}' rm -f '{}c'
      

      这将在更新之前运行,并获取执行更新时将删除或删除的所有 .py 文件,然后删除相应的 .pyc 文件。

      以下是其工作原理的简要说明:

      hg status --no-status --removed --deleted --include "**.py" --rev .:$HG_PARENT1
      

      这会删除当前修订版. 和目标 ($HG_PARENT) 之间的所有文件(例如 hg forget)或删除(hg rmhg mv 等)。如果您使用该功能,您也可以添加 --subrepos 以获取子存储库中的所有更改。

      xargs -0 -I '{}' rm -f '{}c'
      

      这只是在从hg status 返回的每个文件名的末尾添加一个“c”并尝试将其删除。 rm-f 标志确保在 .pyc 文件不存在时不会出错。

      请注意,mercurial 会在更新后自动删除空目录,但孤立的 .pyc 文件通常会导致目录被遗弃。由于它在更新之前运行,因此可以确保正确删除空目录。

      【讨论】:

      • 你能解释一下它是如何工作的吗?它似乎只包括(已删除/删除)以前存储在 Mercurial 中的 .pyc 文件,但没有 .pyc 文件存储在 Mercurial 中。
      • 你是对的,纠正了一个错字。现在应该很清楚了,但我也添加了更彻底的解释
      【解决方案3】:

      我实际做了什么:

      1) 我正在考虑 Nicholas Knight 关于使用适当部署策略的建议。我一直在阅读有关 BuildoutCollective.hostout 的信息以了解更多信息。对于我的项目相对简单的需求,我需要确定这样的重量级策略是否值得。

      2) 我在短期内采用了 Ry4an 的更新钩子概念,直到我决定为止。

      3) 我忽略了 Ry4an 关于过度杀伤的警告,并编写了一个 Python 脚本来仅删除杂散的 .pyc 文件。

      #!/usr/bin/env python
      """ Searches subdirectories of the current directory looking for .pyc files which
          do not have matching .py files, and deletes them.
      
          This is useful as a hook for version control when Python files are moved.
          It is dangerous for projects that deliberately include Python 
          binaries without source.
      """
      import os
      import os.path
      for root, dirs, files in os.walk("."):
          pyc_files = filter(lambda filename: filename.endswith(".pyc"), files)
          py_files = set(filter(lambda filename: filename.endswith(".py"), files))
          excess_pyc_files = filter(lambda pyc_filename: pyc_filename[:-1] not in py_files, pyc_files)
          for excess_pyc_file in excess_pyc_files:
              full_path = os.path.join(root, excess_pyc_file)
              print "Removing old PYC file:", full_path
              os.remove(full_path)
      

      我的更新挂钩现在调用它而不是其他人建议的“查找”命令。

      【讨论】:

      • 那行得通。如果您愿意,可以让 udpate 挂钩直接调用您的 .py 文件的子例程。您只需将其命名为 hook 并提供 .py 文件的路径。这将节省您启动一个完整的“另一个 python 虚拟机”。
      • 谢谢,Ry4an。希望我能给你更多的代表这个建议。
      • 为了后代,这个find命令加sh循环类似:find . -path './virtualenv/*' -prune -or -name '*.pyc' -print | while read f; do [[ ! -f "${f%?}" ]] && echo "$f" && rm "$f"; done
      【解决方案4】:

      我使用.hgignore 文件来跳过所有 .pyc 和 .py~(编辑器的临时文件)的版本控制。例如,这是我的版本:

      # use glob syntax.
      syntax: glob
      
      .directory
      *.pyc
      *~
      *.o
      *.tgz
      *.tbz2
      *.gz
      *.bz2
      

      如果您不仅想忽略噪音,而且想将噪音从本地工作区中删除,那么在更新时添加一个挂钩以删除它们也是一个有趣的技巧。

      【讨论】:

      • 谢谢,edomaur,但我已经有一个 .hgignore 文件(实际上是两个 - 一个跨项目,另一个特定于项目。)我没有对 .pyc 文件进行版本控制。这不是根本问题。
      • 好的,我不确定你的目标是什么,但我想我现在明白了。
      【解决方案5】:
      1. 不要将 .pyc 文件存储在存储库中。
      2. 使用以下命令自动删除 .pyc: find 。 -name '*.pyc' -delete
      3. 在 Python 中开发时使用 -B 参数。

      【讨论】:

      • 另外,预编译版本中的所有 .pyc 文件。您可以通过标记 repo 并推送到生产环境等方式进行部署。编译 .pyc 文件适合其中。对于其他语言,编译二进制文件是天底下最自然的事情。
      • 1) 我没有将 .pyc 文件存储在存储库中。 2)我喜欢这个命令。另请参阅stackoverflow.com/questions/785519/… 了解更多信息。我想我正在寻找“自动化”的帮助。 3)我查了这个。不要为导入的模块存储字节码?为什么不呢?
      • 为什么这个答案没有回答问题时有 16 票赞成?
      • 大约 2.,为什么不rm *.pyc?如果存在子文件夹,则递归删除 pyc?
      【解决方案6】:

      在服务器端使用update hook 怎么样?把它放在仓库的.hg 目录的hgrc 文件中:

      [hooks]
      update = find . -name '*.pyc' | xargs rm
      

      每当您在服务器上更新时,这将删除所有 .pyc 文件。如果您担心重建所有 .pyc 文件的成本,您总是可以更聪明一点,只删除没有 .py 的 .pyc 文件,但这可能有点过头了。

      【讨论】:

      • 谢谢。这是我需要的信息。我继续前进,过度杀戮。请参阅我对这个问题的回答。
      【解决方案7】:

      你需要:

      1) 一个真正的部署基础设施,即使它只是一个 shell 脚本,它可以完成所有工作。从源代码管理中克隆/签出更新的副本不是部署策略。

      2) 任何部署系统都应该彻底清理目录结构。我通常的偏好是每次部署都发生在一个以日期+时间戳命名的新目录上,并且更新一个符号链接(名称如“current”)以指向新目录。如果出现问题,这将为您提供每台服务器上的面包屑。

      3) 修复正在运行的 Python 代码。新的 .py 源文件应始终优先于缓存的 .pyc 文件。如果这不是您所看到的行为,那就是一个错误,您需要找出它发生的原因。

      【讨论】:

      • Python 很简单,复制 .py 文件(以及您需要的任何其他文件)并忽略 .pyc 文件(好吧,你明白了)。
      • 至第 3 点,它没有发生的原因是 .py 不存在。没有 .py 就没有时间进行比较,python 不会忽略没有 .py 的 pyc。
      • 请详细说明 1)。除了这里讨论的 .pyc 文件之外,“hg pull -u”策略对我来说效果很好。我应该提到我只有一台目标机器(尽管我有几个用于测试的存储库)。我的登台机器和生产机器是相同的,但使用不同的帐户和配置文件,因此它们不会互相踩踏。性能、可用​​性和可扩展性对这个项目并不重要。
      • 性能、可用​​性和可扩展性在某种程度上是任何有意义的项目的默认要求,这引发了人们对您正在做什么的疑问。然而,原始经验告诉您,您不应该假设您可以预测哪些杂散文件可能会进入部署的树。这样做时,您会犯一个经典的工程错误,即尝试纠正每个可能的个别问题,而不是试图让除了“正确的事情”之外的任何事情都不可能发生。前一条路是疯狂。
      • 我想确保我已经理解了你的关键点:从 Mercurial 中提取最新文件不是一个(足够的)部署策略,因为它可能会遇到我遇到的确切类型的持续问题:流浪文件以不可预知的方式泄漏到影响生产服务器的目录树中。那正确吗?再次感谢;值得深思。
      猜你喜欢
      • 2011-12-16
      • 1970-01-01
      • 1970-01-01
      • 2014-02-27
      • 2013-07-18
      • 1970-01-01
      • 2010-11-07
      • 1970-01-01
      • 2015-09-23
      相关资源
      最近更新 更多