【问题标题】:How to get the hash of a given source file and related source files in python?如何在python中获取给定源文件和相关源文件的哈希?
【发布时间】:2016-02-24 20:12:24
【问题描述】:

我有一个源文件,比如a.py,它导入了b.py 和一些内置模块。 b.py 可能会进一步导入c.pyd.py 等。在a.py 中,有一个缓慢的操作会生成一个对象作为结果。为了提高速度,我使用pickle 模块转储生成的对象,如果之前生成过,则加载。

但是,如果修改了abcd 源代码中的任何一个,则应重新生成对象。为了避免每次手动删除泡菜文件,我想计算源的哈希并将其写入泡菜文件。所以我可以检查哈希码并决定是否生成对象。

如何编写一个函数,如果给定a.py,它将递归找到b.pyc.pyd.py,并一起计算哈希码?

有没有更好的方法来处理这个问题?

【问题讨论】:

  • 我觉得这有点复杂,你是在做一个编译器的功能。
  • 令人困惑。您是在生成对象还是模块?在一个句子中你说模块,在另一个句子中你说对象。 是的。我知道一个模块在 Python 中有一个表示是 module 类型的对象,但我想了解这个概念
  • @ElmoVanKielmo 对不起我的错误。我的意思是生成一个对象,它会花费很多时间。
  • 我认为查找所有“相关”文件的问题在于您必须知道哪些导入要遵循,哪些不是。我会将所有相关文件放在一个目录中,列出所有这些文件并在.py 上列出所有这些文件的内容并对其进行哈希处理。
  • @jochen 我想我可以关注与 a.py 位于同一文件夹中的源文件。但是我不知道如何获取导入的源文件列表。

标签: python pickle


【解决方案1】:

你可以这样做:

import sys
for name, module in sys.modules.iteritems():
    # module object is a representation of imported module
    try:
        # Next line shows how to access path of Python module file
        module.__file__ 
    except AttributeError:
        '''
        Built-in modules and other special cases don't have __file__
        attribute but you shouldn't care about them as their behaviour won't change
        '''

现在您可以计算和比较您的哈希值。但老实说,我会说比较文件修改时间比计算哈希值足够且便宜。

print sys.modules 在我的例子中的输出是:

{'copy_reg': <module 'copy_reg' from '/usr/lib64/python2.7/copy_reg.pyc'>, 'sre_compile': <module 'sre_compile' from '/usr/lib64/python2.7/sre_compile.pyc'>, '_sre': <module '_sre' (built-in)>, 'encodings': <module 'encodings' from '/usr/lib64/python2.7/encodings/__init__.pyc'>, 'site': <module 'site' from '/usr/lib64/python2.7/site.pyc'>, '__builtin__': <module '__builtin__' (built-in)>, 'sysconfig': <module 'sysconfig' from '/usr/lib64/python2.7/sysconfig.pyc'>, 'atexit': <module 'atexit' from '/usr/lib64/python2.7/atexit.pyc'>, '__main__': <module '__main__' (built-in)>, 'encodings.encodings': None, 'abc': <module 'abc' from '/usr/lib64/python2.7/abc.pyc'>, 'posixpath': <module 'posixpath' from '/usr/lib64/python2.7/posixpath.pyc'>, '_weakrefset': <module '_weakrefset' from '/usr/lib64/python2.7/_weakrefset.pyc'>, 'errno': <module 'errno' (built-in)>, 'encodings.codecs': None, 'sre_constants': <module 'sre_constants' from '/usr/lib64/python2.7/sre_constants.pyc'>, 're': <module 're' from '/usr/lib64/python2.7/re.pyc'>, '_abcoll': <module '_abcoll' from '/usr/lib64/python2.7/_abcoll.pyc'>, 'types': <module 'types' from '/usr/lib64/python2.7/types.pyc'>, '_codecs': <module '_codecs' (built-in)>, 'encodings.__builtin__': None, '_warnings': <module '_warnings' (built-in)>, 'genericpath': <module 'genericpath' from '/usr/lib64/python2.7/genericpath.pyc'>, 'stat': <module 'stat' from '/usr/lib64/python2.7/stat.pyc'>, 'zipimport': <module 'zipimport' (built-in)>, '_sysconfigdata': <module '_sysconfigdata' from '/usr/lib64/python2.7/_sysconfigdata.pyc'>, 'warnings': <module 'warnings' from '/usr/lib64/python2.7/warnings.pyc'>, 'UserDict': <module 'UserDict' from '/usr/lib64/python2.7/UserDict.pyc'>, 'encodings.utf_8': <module 'encodings.utf_8' from '/usr/lib64/python2.7/encodings/utf_8.pyc'>, 'sys': <module 'sys' (built-in)>, 'codecs': <module 'codecs' from '/usr/lib64/python2.7/codecs.pyc'>, 'readline': <module 'readline' from '/usr/lib64/python2.7/lib-dynload/readline.so'>, 'os.path': <module 'posixpath' from '/usr/lib64/python2.7/posixpath.pyc'>, '_locale': <module '_locale' from '/usr/lib64/python2.7/lib-dynload/_locale.so'>, 'rlcompleter': <module 'rlcompleter' from '/usr/lib64/python2.7/rlcompleter.pyc'>, 'signal': <module 'signal' (built-in)>, 'traceback': <module 'traceback' from '/usr/lib64/python2.7/traceback.pyc'>, 'linecache': <module 'linecache' from '/usr/lib64/python2.7/linecache.pyc'>, 'posix': <module 'posix' (built-in)>, 'encodings.aliases': <module 'encodings.aliases' from '/usr/lib64/python2.7/encodings/aliases.pyc'>, 'exceptions': <module 'exceptions' (built-in)>, 'sre_parse': <module 'sre_parse' from '/usr/lib64/python2.7/sre_parse.pyc'>, 'os': <module 'os' from '/usr/lib64/python2.7/os.pyc'>, '_weakref': <module '_weakref' (built-in)>}

编辑:

怎么样:

import sys
import copy

# Save the dict of imported modules
modules_before = copy.copy(sys.modules)

# Import b, which will import c and d and so on
import b

for name, module in sys.modules.iteritems():
    if name in modules_before:
        # Skip irrelevant modules
        continue
    # module object is a representation of imported module
    try:
        # Next line shows how to access path of Python module file
        module.__file__ 
    except AttributeError:
        '''
        Built-in modules and other special cases don't have __file__
        attribute but you shouldn't care about them as their behaviour won't change
        '''

【讨论】:

  • 我同意你的看法。比较修改时间是一个更好的主意。
  • 这似乎不仅会列出 a.py 导入的模块,还会列出 Python 运行时导入的所有模块。
  • 是的。问题是?
  • 如果您真的坚持只检查特定文件夹和子文件夹中的模块 - if module.__file__.startswith('/path/to/my/fancy/folder'): 但检查导入的所有内容的修改时间仍然是几毫秒的问题。
  • 假设有一个top.py,它导入something_else.py和a.py。如果 top.py、something_else.py 或 something_else.py 导入的任何文件被修改,对象将被重新生成。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-11-11
  • 2010-11-16
  • 1970-01-01
  • 2020-04-03
  • 1970-01-01
  • 2020-01-28
  • 1970-01-01
相关资源
最近更新 更多