从本质上讲,我想在堆栈上放置一个变量,该变量可以通过堆栈下面的所有调用到达,直到块退出.在Java中,我将使用支持方法的本地静态线程解决此问题,然后可以从方法访问.
典型示例:您收到请求,并打开数据库连接.在请求完成之前,您希望所有代码都使用此数据库连接.完成并关闭请求后,关闭数据库连接.
我需要这个,是一个报告生成器.每个报告由多个部分组成,每个部分可以依赖于不同的计算,有时不同的部分部分依赖于相同的计算.由于我不想重复繁重的计算,我需要缓存它们.我的想法是用缓存装饰器装饰方法.缓存根据方法名称和模块创建一个id,它的参数,看它是否已经在堆栈变量中计算,并且如果没有则执行该方法.
我将通过展示我当前的实现来尝试清除.我想要做的是简化那些实现计算的代码.
首先,我有中央缓存访问对象,我称之为MathContext:
class MathContext(object):
def __init__(self, fn):
self.fn = fn
self.cache = dict()
def get(self, calc_config):
id = create_id(calc_config)
if id not in self.cache:
self.cache[id] = calc_config.exec(self)
return self.cache[id]
Run Code Online (Sandbox Code Playgroud)
fn参数是创建上下文的文件名,从中可以读取数据以进行计算.
然后我们有Calculation类:
class CalcBase(object):
def exec(self, math_context):
raise NotImplementedError
Run Code Online (Sandbox Code Playgroud)
这是一个愚蠢的斐波那契例子.这些方法实际上不是递归的,而是处理大量数据,但它可以演示如何依赖其他计算:
class Fibonacci(CalcBase):
def __init__(self, n): self.n = n
def exec(self, math_context):
if self.n < 2: return 1
a = math_context.get(Fibonacci(self.n-1))
b = math_context.get(Fibonacci(self.n-2))
return a+b
Run Code Online (Sandbox Code Playgroud)
我想要斐波那契,只是一种装饰方法:
@cache
def fib(n):
if n<2: return 1
return fib(n-1)+fib(n-2)
Run Code Online (Sandbox Code Playgroud)
使用math_context示例,当math_context超出范围时,它的缓存值也是如此.我想为装饰者做同样的事情.IE浏览器.在第X点,@ cache缓存的所有内容都是deveferrenced.
我的设计如下:
__main__ 引用 aa 引用 bb 引用 aa 创建然后处理 __main__因此,a并b有循环参考.然而在del a我宁愿都a和b处置.
我在很多地方看到使用Context Manager的建议,特别是with语句而不是__del__().但是我with在局部范围内看到的开始和结束的所有例子(例如某种方法)
这可以优雅地执行with吗?
有什么选择?
我最近在Python的with语句中遇到了一个奇怪的行为。我有一个代码,它使用 Python 的上下文管理器来回滚__exit__方法中的配置更改。经理return False在finally 块中有一个值__exit__。我在以下代码中隔离了这种情况 - 唯一的区别是 return 语句的缩进:
class Manager1(object):
def release(self):
pass # Implementation not important
def rollback(self):
# Rollback fails throwing an exception:
raise Exception("A failure")
def __enter__(self):
print "ENTER1"
def __exit__(self, exc_type, exc_val, exc_tb):
print "EXIT1"
try:
self.rollback()
finally:
self.release()
return False # The only difference here!
class Manager2(object):
def release(self):
pass # Implementation not important
def rollback(self):
# Rollback fails throwing an exception:
raise Exception("A failure")
def __enter__(self):
print …Run Code Online (Sandbox Code Playgroud) 我试图用contextmanager隐藏一些try/except复杂性.这是一个简单的例子:
from contextlib import contextmanager
import mpd
mpdclient = mpd.MPDClient()
mpdclient.connect("localhost", 6600)
@contextmanager
def mpdcontext():
try:
yield
except mpd.ConnectionError:
mpdclient.connect("localhost", 6600)
with mpdcontext():
mpdclient.status()
with mpdcontext():
mpdclient.lsinfo()
Run Code Online (Sandbox Code Playgroud)
现在,正如我所理解的那样,在调用yield时执行with语句中的块.在我的情况下,如果这引发异常,我重新连接到mpd.重新连接后,我可以以某种方式再次执行with-block吗?
谢谢
我正在尝试编写一个小型上下文管理器,它将尝试重复执行某些代码,直到代码正常工作或完成指定次数的尝试。我试图写这个,但在让上下文管理器在产生时处理问题时遇到了困难:
Exception RuntimeError: 'generator ignored GeneratorExit'
Run Code Online (Sandbox Code Playgroud)
我应该如何编码?
import contextlib
import random
def main():
with nolube():
print(1 / random.randint(0, 1))
@contextlib.contextmanager
def nolube(
tries = None # None: try indefinitely
):
"""
Create a context for trying something repeatedly.
"""
tries_done = 0
rekt = True
if tries is None:
while rekt is True:
try:
yield
rekt = False
except:
tries_done += 1
pass
else:
while rekt is True and tries_done <= tries:
try:
yield
rekt = False
except:
tries_done += …Run Code Online (Sandbox Code Playgroud) 说,我想打开一些文件并逐行处理.为了论证,让我们假设我想将每个文件中的第n行连接成一行并将其写入另一个文件.我不想让自己的记忆膨胀,所以我不想完全阅读它们.我不知道我的功能会有多少文件.
如果我知道文件的数量,我会做这样的事情:
with open(file_a) as in_a, open(file_b) as in_b, open(file_c, "w") as out:
try:
while True:
line_a = next(in_a)
line_b = next(in_b)
out.write(line_a + line_b)
except StopIteration:
pass
Run Code Online (Sandbox Code Playgroud)
有没有办法用未知数量的输入(或其他上下文管理器)做类似的事情?
作为一个基本示例,请想象以下内容:
with runFiveTimes:
print("test")
Run Code Online (Sandbox Code Playgroud)
这在Python中可能吗?
(这个例子只是为了澄清问题,显然有更简单的方法来实现这个特定的例子)
我如何注释contextmanagerPyCharm 中a的yield类型,以便它正确猜测with子句中使用的值的类型-就像它猜测fcreated in with open(...) as f是文件一样?
例如,我有一个这样的上下文管理器:
@contextlib.contextmanager
def temp_borders_file(geometry: GEOSGeometry, name='borders.json'):
with TemporaryDirectory() as temp_dir:
borders_file = Path(dir) / name
with borders_file.open('w+') as f:
f.write(geometry.json)
yield borders_file
with temp_borders_file(my_geom) as borders_f:
do_some_code_with(borders_f...)
Run Code Online (Sandbox Code Playgroud)
如何让PyCharm知道每个这样borders_f创建的对象都是的pathlib.Path(从而启用上的Path方法的自动完成功能border_f)?当然,我可以像# type: Path在每条with语句之后一样发表评论,但是似乎可以通过适当地注释来完成temp_border_file。
我试过Path,typing.Iterator[Path]并typing.Generator[Path, None, None]作为返回类型的temp_border_file,以及增加# type: Path对borders_file上下文管理的代码中,但似乎它并不能帮助。
我没有重新分配open关键字,但仍然收到此错误。有任何建议或指导来纠正我的错误吗?
with tempfile.mkdtemp() as test_dir:
print(test_dir)
Run Code Online (Sandbox Code Playgroud)
AttributeError: __enter__
我也是python的新手,我很难理解这些概念。
我找到了下面的例子以下对象上下文管理器的File:
class File(object):\n def __init__(self, file_name, method):\n self.file_obj = open(file_name, method)\n def __enter__(self):\n return self.file_obj\n def __exit__(self, type, value, traceback):\n self.file_obj.close()\nRun Code Online (Sandbox Code Playgroud)\n在这里,管理器完成的工作(实际上是打开文件)发生在该__init__方法中。然而,在随附的文本中,他们建议文件打开应该发生在__enter__:
\n\n让\xe2\x80\x99s 谈谈幕后发生的事情。
\n\n
\n- with 语句存储退出File类的
\n- 它调用输入File 类的
\n- 进入打开文件并返回它。
\n- 打开的文件句柄被传递给opened_file。
\n- 我们使用 .write() 写入文件。
\n- with 语句调用存储的退出方法。
\n- 出口关闭文件。
\n
一般来说,哪种方法是正确的?似乎撤销的工作__exit__应该发生在__enter__,而不是__init__因为它们是通过上下文管理器机制 1:1 配对的,但这个例子让我感到怀疑。 …
contextmanager ×10
python ×9
yield ×2
exception ×1
mpd ×1
pycharm ×1
thread-local ×1
try-catch ×1
typing ×1