Python 遥测 - 记录所有 python 加载的模块

Python telemetry - Log all python modules loaded

我正在使用 venv 和 pip 创建一个友好的 python 开发环境,这样用户就可以启动一个 jupyter 笔记本,其中包含他们在 PYTHONPATH 上可能需要的所有库。 为了删除用户未使用的库,我想在集中式 NAS 共享中记录在 Python 执行期间加载的所有库(它们 运行 其主机上的 python 进程,但它们可以写入中央 NAS 共享)。为此,我考虑使用 strace -e trace=open,read python.. 并通过我的库文件路径过滤条目,但我很确定应该有一个标准的 python 库来完成这种遥测工作。

问题

监视用户 python environments/workstations 上的 python 进程以确定要删除哪些未使用的库。

解决方案

我不确定是否有随时可用的独立工具。 strace(正如您在问题中提到的)+ syslog 是一个选项。我知道你提到过将日志保存到 NAS,但我也会考虑使用轻量级 syslog 服务器,因为 syslog 可以处理边缘情况(即:自动重试)并为你提供一个接口,以便能够过滤日志。

参考资料

系统日志过滤器参考:https://www.syslog-ng.com/technical-documents/doc/syslog-ng-open-source-edition/3.17/administration-guide/52#TOPIC-989744

你可以包装 builtins.__input__ 来记录导入的模块的名称,然后 运行 (通过 exec 函数,但我们需要捕获 if __name__ == '__main__': 块所以这可能是不可避免的)您要监视的代码:

loggy.py

#!/usr/bin/env python3

import builtins
import sys

if __name__ == '__main__':

    builtins.__import_copy__ = builtins.__import__

    __libs = set()

    def __import_wrap__(*args,**kwargs):
        __libs.add(args[0])
        return builtins.__import_copy__(*args,**kwargs)

    builtins.__import__ = __import_wrap__

    sys.argv = sys.argv[1:]

    exec(open(sys.argv[0]).read())

    print(__libs)

测试脚本test.py

#!/usr/bin/env python3

import re
import sys

if __name__ == '__main__':
    x = re.findall(r'all\w*',sys.argv[1])
    print(x)

对我来说(Python 3.6.9)这似乎可以记录辅助脚本导入的所有模块:

mostly@ubuntu:~$ python3 loggy.py test.py "allways misspelling"
['allways']
{'_heapq', 'functools', 'collections.abc', 'operator', 'weakref', 'sys', 'copyreg', '_weakref', 'itertools', '_locale', 'abc', '_collections', 'sre_compile', 'enum', 'sre_parse', '_operator', '_collections_abc', '_bootlocale', '_sre', 'sre_constants', '_thread', 'heapq', 'reprlib', 'keyword', '_functools', 're', 'collections', '_weakrefset', 'builtins', 'types'}