正在创建globals()的副本



在python中,我试图编写一个实用函数来计算函数运行所需的时间。它基本上是一个助手函数,使使用timeit变得更容易。

这是我的密码。如果其中任何一个看起来很奇怪,那是因为我试图尽可能多地修剪代码,并使其尽可能简单:

import numpy as np
import timeit
import requests
from enum import Enum
import copy

class LoggingLevel(Enum):
Debug = 1
Info = 2
Important = 3
VeryImportant = 4
SuperImportant = 5
Warning = 6

class Logging:
@staticmethod
def log(message: str, level: LoggingLevel, special, colorized):
colors = {
"Debug": "33[0m",
"Info": "33[94m",
"Important": "33[95m",
"VeryImportant": "33[96m",
"SuperImportant": "33[93m",
"Warning": "33[91m",
"Special": "33[92m",
"reset": "33[0m"
}
if colorized:
if special:
print(f"{colors['Special']}[{level.name}] [Special]: {message}{colors['reset']}")
else:
if level.name in colors:
print(f"{colors[level.name]}[{level.name}]: {message}{colors['reset']}")
else:
print(f"[{level.name}]: {message}")

logging = Logging()

def check_internet(testurl: str = "https://www.example.com", timeout: float = 5) -> bool:
logging.log("Checking for internet connection with timeout of"
f" {timeout if timeout is not None else ''} seconds...",
LoggingLevel.Info, special=False, colorized=True)
logging.log(f"Using {testurl} to check for internet connection", LoggingLevel.Debug, special=False, colorized=True)
try:
requests.get(testurl, timeout=timeout)
logging.log(f"Successfully confirmed internet connection!", LoggingLevel.Info, special=False, colorized=True)
return True
except (requests.ConnectionError, requests.Timeout):
return False

def time(code: str, useglobals: bool = True, sets: int = 3, trialsperset: int = 10) -> float:
"""
Times how long a segment of code takes to run (on average) using the timeit module
Usually used to test functions
:param code: The segment of code to test
:param useglobals: Whether to use the current globals or no globals in the
timing sandbox (the code may not work without them)
:param sets: The number of sets
:param trialsperset: The number of times to run the code each set
(Total number of times run = sets * trials)
the higher the number, the more accurate, but also the longer it will take
:return: Average amount of time the code takes to run (seconds)
"""
# noinspection IncorrectFormatting
class NopClass:
""" From https://stackoverflow.com/a/24946360/20558255 """
def nop(*args, **kwargs): pass
def __getattr__(self, _): return self.nop
nopclass = NopClass()
nopfunction: callable = lambda *args, **kwargs: None
logging.log(f"Testing how long {code} takes to run in {sets} sets"
f" of {trialsperset} trials...", LoggingLevel.Debug, special=False, colorized=True)
if useglobals:
sandboxglobals = copy.deepcopy(globals())
# We nop logging class and print function so we don't get flooded with print messages
sandboxglobals["print"] = nopfunction
sandboxglobals["logging"] = nopclass
else:
sandboxglobals = None
times = timeit.repeat(stmt=code, repeat=sets, number=trialsperset, globals=sandboxglobals)
return np.mean(times)
time("check_internet()", useglobals=True, sets=3, trialsperset=10)

希望你能理解为什么我(试图)将globals()复制到sandboxglobals中,并对sandboxglobals进行一些更改,然后将sandboxglobals传递到timeit.repeat:我想在代码计时时禁用它的打印和日志记录。但是,我不想禁用实际程序的打印和日志记录。尽管在这种情况下,可以在调用timeit.repeat()之前禁用实际程序的打印和日志记录,然后在调用之后重新启用它们,但在其他情况下(例如异步或多线程代码),这很重要。

但是,deepcopy不起作用。当我运行代码时,我得到这个错误:

Traceback (most recent call last):
File "Test.py", line 98, in <module>
time("check_internet()", useglobals=True, sets=3, trialsperset=10)
File "Test.py", line 87, in time
sandboxglobals = copy.deepcopy(globals())
File "C:UserszachyAppDataLocalProgramsPythonPython310libcopy.py", line 146, in deepcopy
y = copier(x, memo)
File "C:UserszachyAppDataLocalProgramsPythonPython310libcopy.py", line 231, in _deepcopy_dict
y[deepcopy(key, memo)] = deepcopy(value, memo)
File "C:UserszachyAppDataLocalProgramsPythonPython310libcopy.py", line 161, in deepcopy
rv = reductor(4)
TypeError: cannot pickle 'module' object

我理解这个错误的意思,但我不知道如何解决它。我尝试了我能找到的一切,但我找不到一种不酸洗就深度复制的方法。

浅拷贝不起作用,因为它不是递归的——它会禁用print,因为这是globals()dict中的顶级,但它不会禁用logging.log。作为证明,以下是将deepcopy更改为copy:后的日志

[Debug]: Testing how long check_internet() takes to run in 3 sets of 10 trials...
[Info]: Checking for internet connection with timeout of 5 seconds...
[Debug]: Using https://www.example.com to check for internet connection
[Info]: Successfully confirmed internet connection!
[Info]: Checking for internet connection with timeout of 5 seconds...
[Debug]: Using https://www.example.com to check for internet connection
[Info]: Successfully confirmed internet connection!
... [TRUNCATED]

有什么方法可以实现我想要的吗?还是不可能?我有什么东西不见了吗?谢谢

由于您不需要对sandboxglobals中的模块信息进行任何修改,因此您可以跳过从globals中对其进行深度复制。

# noinspection IncorrectFormatting
class NopClass:
""" From https://stackoverflow.com/a/24946360/20558255 """
def nop(*args, **kwargs): pass
def __getattr__(self, _): return self.nop
nopclass = NopClass()
nopfunction: callable = lambda *args, **kwargs: None
logging.log(f"Testing how long {code} takes to run in {sets} sets"
f" of {trialsperset} trials...", LoggingLevel.Debug, special=False, colorized=True)
if useglobals:
sandboxglobals = {}
for k,v in globals().items():
try:
# entries of modules raise exception
# do not deepcopy them
tmp_dict = copy.deepcopy({k:v})
sandboxglobals.update(tmp_dict)
except:
tmp_dict = {k:v}
sandboxglobals.update(tmp_dict)
# We nop logging class and print function so we don't get flooded with print messages
sandboxglobals["print"] = nopfunction
sandboxglobals["logging"] = nopclass
else:
sandboxglobals = None
times = timeit.repeat(stmt=code, repeat=sets, number=trialsperset, globals=sandboxglobals)
return np.mean(times)

相关内容

  • 没有找到相关文章

最新更新