gpt4 book ai didi

python - 可以知道 python 模块是否已重新加载吗?

转载 作者:行者123 更新时间:2023-12-01 01:49:25 25 4
gpt4 key购买 nike

我正在尝试找出错误的原因:https://github.com/numba/numba/issues/3027

似乎(对于某些 numba 用户,但不是全部)

import sys
import numba

@numba.njit
def some_func(begin1, end1, begin2, end2):
if begin1 > begin2: return some_func(begin2, end2, begin1, end1)
return end1 + 1 >= begin2

sys.stdout = sys.stderr
x = id(sys.stdout)
some_func(0,1,2,3)
y = id(sys.stdout)
assert x==y # Fail

sys.stdout 的值在调用 somefunc 之前和之后有所不同。我想知道这是否是因为:

  • reload(sys) 被调用,或者
  • sys.stdout 已重新分配

这似乎很难知道,因为如果调用了重新加载,分配给模块 namespace 的变量将在重新加载后继续存在,除非它们由模块本身重新初始化:

import sys
sys.stdout = None
sys.zzz = 123
sys = reload(sys)
sys.stderr.write("sys.stdout = {}\n".format(sys.stdout)) # Reset to file object
sys.stderr.write("sys.zzz = {}\n".format(sys.zzz)) # Surprise success!
sys.stderr.flush()

最佳答案

虽然非常不受欢迎,some Python 2 code reloads sys to restore the sys.setdefaultencoding() function 。这几乎总是导致此问题的原因。

所以你可以检测到 sys通过检查 setdefaultencoding 重新加载属性:

if hasattr(sys, 'setdefaultencoding'):
# sys was reloaded!

这仅适用于 Python 2。或者您可以增强 sys.flags struct sequence有一个额外的字段:

from collections import namedtuple
import sys, re

_sys_flags_fields = re.findall('(\w+)=\d', repr(sys.flags))
_sys_flags_augmented = namedtuple('flags', _sys_flags_fields + ['sys_not_reloaded'])
sys.flags = _sys_flags_augmented(*sys.flags + (1,))

之后您可以测试:

if not getattr(sys.flags, 'sys_not_reloaded', 0):

增强sys.flags比大多数其他产品更安全sys操作,因为第三方代码可能依赖于记录的 sys属性和方法不可篡改,它也适用于 Python 3。

您可以阻止 sys通过包装 __builtin__.reload 重新加载/importlib.reload/imp.reload :

try:
# Python 2
import __builtin__ as targetmodule
except ImportError:
# Python 3.4 and up
try:
import importlib as targetmodule
targetmodule.reload # NameError for older Python 3 releases
except (ImportError, AttributeError):
# Python 3.0 - 3.3
import imp as targetmodule

from functools import wraps

def reload_wrapper(f):
@wraps(f)
def wrapper(module):
if getattr(module, '__name__', None) == 'sys':
raise ValueError('sys should never be reloaded!')
return f(module)
return wrapper

targetmodule.reload = reload_wrapper(targetmodule.reload)

您可以使用 warnings module,而不是引发异常。或其他一些机制来记录或发出噪音 sys正在重新加载;您可能想要include the caller进入这样的警告。

尽早执行上述模块,以确保您可以捕获正在执行此操作的代码,可能的方法是将其插入 sitecustomize模块,或通过 .pth 触发它文件安装到 site-packages目录。 .pth 中的任意行以 import 开头的文件是 executed as Python code by the site.py module at Python startup ,因此在这样的文件中包含以下内容:

import yourpackage.sysreload_neutraliser

将在 Python 启动时注入(inject)导入。

关于python - 可以知道 python 模块是否已重新加载吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50880121/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com