这是我正在使用的代码:
from contextlib import contextmanager
from functools import wraps
class with_report_status(object):
def __init__(self, message):
self.message = message
def __call__(self, f):
@wraps(f)
def wrapper(_self, *a, **kw):
try:
return f(_self, *a, **kw)
except:
log.exception("Handling exception in reporting operation")
if not (hasattr(_self, 'report_status') and _self.report_status):
_self.report_status = self.message
raise
return wrapper
class MyClass(object):
@contextmanager
@with_report_status('unable to create export workspace')
def make_workspace(self):
temp_dir = tempfile.mkdtemp()
log.debug("Creating working directory in %s", temp_dir)
self.workspace = temp_dir
yield self.workspace
log.debug("Cleaning up working directory in %s", temp_dir)
shutil.rmtree(temp_dir) …Run Code Online (Sandbox Code Playgroud) 我有一个返回上下文管理器的迭代器。
我想要一个 pythonicwith语句,它模拟多个嵌套语句的行为with,每个嵌套语句对应迭代器返回的每个上下文管理器。
有人可能会说,我想要(已弃用的)函数的泛化contextlib.nested。
我想采用任意数量的路径来表示嵌套的tar档案,并对最里面的档案执行操作.问题是,嵌套可以是任意的,因此我需要的上下文管理器的数量也是任意的.
举个例子:
ARCHIVE_PATH = "path/to/archive.tar"
INNER_PATHS = (
"nested/within/archive/one.tar",
"nested/within/archive/two.tar",
# Arbitary number of these
)
def list_inner_contents(archive_path, inner_paths):
with TarFile(archive_path) as tf1:
with TarFile(fileobj=tf1.extractfile(inner_paths[0])) as tf2:
with TarFile(fileobj=tf2.extractfile(inner_paths[1])) as tf3:
# ...arbitary level of these!
return tfX.getnames()
contents = list_inner_contents(ARCHIVE_PATH, INNER_PATHS))
Run Code Online (Sandbox Code Playgroud)
我不能使用with语句的嵌套语法,因为可以嵌套任意数量的级别.我无法使用,contextlib.nested因为文档在那里说:
...
nested()用于打开两个文件是一个编程错误,因为如果在打开第二个文件时抛出异常,第一个文件将不会立即关闭.
有没有办法使用语言结构来执行此操作,还是需要手动管理我自己的打开文件对象堆栈?
对于要在with块中使用的类或函数是否存在通用命名约定,例如
with CreateSomeContext() as x:
...
Run Code Online (Sandbox Code Playgroud)
?是否表示应该使用函数的类或结果with?
我读到这里,它是推荐使用with open(filename),而不是使用对open(filename)和filename.close()(至少对基本任务),并且它也是更好地使用try.
Q1:如果我的理解是正确的,那么正确的顺序是什么?
try:
with open(filename) as f:
do something, eg. match string
Run Code Online (Sandbox Code Playgroud)
要么
with open(filename) as f:
try:
do something, eg. match string
Run Code Online (Sandbox Code Playgroud)
Q2:如果我还想插入一些代码来弹出文件处理错误的弹出窗口,哪种情况更好?(找不到文件,或者其他东西)
考虑以下 Python 代码:
def values():
with somecontext():
yield 1
yield 2
for v in values():
print(v)
break
Run Code Online (Sandbox Code Playgroud)
在这种情况下,Python 是否保证生成器已正确关闭,从而退出上下文?
我意识到在实践中,由于引用计数和生成器的急切破坏,在 CPython 中会出现这种情况,但是 Python 是否保证这种行为?我确实注意到它在 Jython 中确实不起作用,所以这应该被视为错误还是允许的行为?
假设我们有以下内容mod.py:
def __enter__():
print("__enter__<")
def __exit__(*exc):
print("__exit__< {0}".format(exc))
class cls:
def __enter__(self):
print("cls.__enter__<")
def __exit__(self, *exc):
print("cls.__exit__< {0}".format(exc))
Run Code Online (Sandbox Code Playgroud)
以及它的以下用途:
import mod
with mod:
pass
Run Code Online (Sandbox Code Playgroud)
我收到一个错误:
Traceback (most recent call last):
File "./test.py", line 3, in <module>
with mod:
AttributeError: __exit__
Run Code Online (Sandbox Code Playgroud)
根据文档文档,该with语句应如下执行(我相信它在步骤2失败,因此截断列表):
- 评估上下文表达式(with_item中给出的表达式)以获取上下文管理器.
__exit__()加载上下文管理器以供以后使用.__enter__()调用上下文管理器的方法.- 等等...
据我所知,没有理由找不到原因__exit__.是否有一些我错过了使模块无法作为上下文管理器工作的东西?
python python-module with-statement contextmanager python-3.x
我有以下代码,我只想 使用contextmanager来使用日志记录模块.
from contextlib import contextmanager
import logging
@contextmanager
def log_level(level, name):
logger = logging.getLogger(name)
old_level = logger.getEffectiveLevel()
print('log_level.old_level: ' + str(old_level))
logger.setLevel(level)
print('log_level.new_level: ' + str(logger.getEffectiveLevel()))
try:
yield logger
finally:
logger.setLevel(old_level)
if __name__ == '__main__':
with log_level(logging.DEBUG, 'my-log') as logger:
print('__main__.log_level.logger.level: ' + str(logger.getEffectiveLevel()))
logger.debug('Debug with logger: will print')
logger.warning('Warning')
print('__main__.log_level.logger.level: ' + str(logger.getEffectiveLevel()))
print('__main__.logger.level: ' + str(logger.getEffectiveLevel()))
Run Code Online (Sandbox Code Playgroud)
可以看出,在main.log_level中,记录器级别应该是DEBUG,它应该打印消息'Debug with logger:will print'.但是,当我运行代码时,此调试消息不会打印.查看代码的打印件,它表示记录器在log_level内部具有DEBUG级别,并且当它退出log_level时级别返回到WARNING.这是我的输出,当使用python 3执行时:
log_level.old_level: 30
log_level.new_level: 10
__main__.log_level.logger.level: 10
Warning
__main__.log_level.logger.level: 10
__main__.logger.level: 30
Run Code Online (Sandbox Code Playgroud)
我想帮助理解为什么 …
什么是正确的类型签名__exit__?我有以下几点:
from types import TracebackType
from typing import Optional, Type
class Foo:
def __enter__(self) -> 'Foo':
return self
def __exit__(self, exc_type: Optional[Type[BaseException]],
exc_value: Optional[BaseException],
traceback: Optional[TracebackType]) -> bool:
return False
Run Code Online (Sandbox Code Playgroud)
在最近的mypy(0.560)上,此类型检查是否正确(--strict我对此签名有一定的信心,因为我从排版的内部偷了它)。
当此脚本与python 3.6一起运行时,按预期没有任何反应。但是当使用3.5.2运行时,我们会得到一个例外:
Traceback (most recent call last):
File "/home/student/mypy_test/test.py", line 4, in <module>
class Foo: #(ContextManager['Foo']):
File "/home/student/mypy_test/test.py", line 8, in Foo
def __exit__(self, exc_type: Optional[Type[BaseException]],
File "/usr/lib/python3.5/typing.py", line 649, in __getitem__
return Union[arg, type(None)]
File "/usr/lib/python3.5/typing.py", line 552, in __getitem__
dict(self.__dict__), parameters, _root=True)
File …Run Code Online (Sandbox Code Playgroud) 我的问题是,如何在不使用的情况下执行任何上下文管理器with?
Python 有上下文管理器的思想,
代替
file = open('some_file', 'w')
try:
file.write('Hola!')
finally:
file.close()
# end try
Run Code Online (Sandbox Code Playgroud)
你可以写
with open('some_file', 'w') as opened_file:
opened_file.write('Hola!')
# end with
Run Code Online (Sandbox Code Playgroud)
虽然在大多数情况下,第二个是黄金解决方案,但对于在交互式控制台中进行测试和探索,第一个可以更好地使用,因为您可以一行一行地编写它。
>>> file = open('some_file', 'w')
>>> file.write('Hola!')
>>> file.close()
Run Code Online (Sandbox Code Playgroud)
我的问题是,我如何执行这样的with上下文管理器,最适合探索?
我的实际用例如下,但请尝试给出一个通用的答案,并且也适用于其他上下文管理器。
import flask
app = flask.Flask(__name__)
with app.test_request_context('/?name=Peter'):
assert flask.request.path == '/'
assert flask.request.args['name'] == 'Peter'
Run Code Online (Sandbox Code Playgroud)
contextmanager ×10
python ×10
python-3.x ×3
decorator ×1
generator ×1
iterator ×1
logging ×1
mypy ×1
nested ×1
python-2.7 ×1
python-3.5 ×1
try-catch ×1