生成器可以管理资源,例如通过yield从上下文管理器内部进行操作。一旦close()调用生成器的方法(或引发异常),资源就会被释放。
由于很容易忘记close()最后调用,我认为显然也可以使用上下文管理器(并且还可以处理潜在的异常)。我知道我可以使用contextlib.closing它,但是直接在语句中使用生成器不是更好吗with?
生成器不应该是上下文管理器有什么原因吗?
我有
with open ('~/abc.csv', 'w') as f:
write1 = csv.write(f)
write1.writerow(['header1', 'header2', 'header3', 'header4'])
with open ('~/def.csv', 'w') as g:
write2 = csv.write(g)
write2.writerow(['header1', 'header2', 'header3', 'header4', 'header5', 'header6'])
for iteration in a_list:
perform calculations
result1 = ([h1, h2, h3, h4],[l1, l2, l3, l4],[m1, m2, m3, m4], ...,[])
for pa in result1:
write1.writerow(pa)
def fun(result1):
result2 = ([n1, n2, n3, n4, n5, n6],[p1, p2, p3, p4, p5, p6], [], ...[])
for pb in result2:
write2.writerow(pb)
Run Code Online (Sandbox Code Playgroud)
期望两个 csv 文件为
'header1', 'header2', …Run Code Online (Sandbox Code Playgroud) 使用 Python 2.7.9,我试图排除 mysql 连接和游标的打开和关闭
代码是
class MySQLCursor:
def __init__(self, commit=False):
self.commit = commit
def __enter__(self):
self.conn = MySQLdb.connect(host=_MYMYSQLHOST,
user=_MYMYSQLUSER,
passwd=_MYMYSQLPASSWD,
db=_MYMYSQLDB)
self.cursor = self.conn.cursor()
return self.cursor
def __exit__(self, exc_type, exc_val, exc_tb):
if self.commit:
self.conn.commit()
self.cursor.close()
self.conn.close()
return
Run Code Online (Sandbox Code Playgroud)
使用它作为
with MySQLCursor as cursor:
cursor.execute("SELECT VERSION()")
row = cursor.fetchone()
print "server version:", row[0]
Run Code Online (Sandbox Code Playgroud)
我收到错误消息
AttributeError: __exit__
Run Code Online (Sandbox Code Playgroud)
这是 mysql 问题还是上下文管理器问题?
我最近一直在想是否有一种方法可以检测上下文管理器是否嵌套。
我创建了Timer和TimerGroup类:
class Timer:
def __init__(self, name="Timer"):
self.name = name
self.start_time = clock()
@staticmethod
def seconds_to_str(t):
return str(timedelta(seconds=t))
def end(self):
return clock() - self.start_time
def print(self, t):
print(("{0:<" + str(line_width - 18) + "} >> {1}").format(self.name, self.seconds_to_str(t)))
def __enter__(self):
return self
def __exit__(self, exc_type, value, traceback):
self.print(self.end())
class TimerGroup(Timer):
def __enter__(self):
print(('= ' + self.name + ' ').ljust(line_width, '='))
return self
def __exit__(self, exc_type, exc_val, exc_tb):
total_time = self.seconds_to_str(self.end())
print(" Total: {0}".format(total_time).rjust(line_width, '='))
print()
Run Code Online (Sandbox Code Playgroud)
此代码以可读格式打印时间:
with TimerGroup("Collecting child documents for …Run Code Online (Sandbox Code Playgroud) 我只是不知道如何使用 aiosqlite 模块,以便我可以保持连接以备后用。
基于aiosqlite 项目页面的示例
async with aiosqlite.connect('file.db') as conn:
cursor = await conn.execute("SELECT 42;")
rows = await cursor.fetchall()
print('rows %s' % rows)
Run Code Online (Sandbox Code Playgroud)
工作正常,但我想保持连接,以便我可以在整个程序中使用它。
通常,使用 sqlite,我会打开一个连接,将其存储起来,然后在程序的整个生命周期中使用它。
我也尝试过这样的事情:
conn = aiosqlite.connect('file.db')
c = await conn.__enter__()
AttributeError: 'Connection' object has no attribute '__enter__'
Run Code Online (Sandbox Code Playgroud)
有没有办法在没有上下文管理器的情况下使用这个模块?
考虑以下 python 代码,它使用上下文管理器来获取和释放资源:
from contextlib import contextmanager
@contextmanager
def res(i):
print(f'Opening resource {i}')
yield
print(f'Closing resource {i}')
Run Code Online (Sandbox Code Playgroud)
现在假设我们需要使用其中一些资源
with res(0), res(1), res(2):
print('Using resources.')
Run Code Online (Sandbox Code Playgroud)
其中内部部分取决于同时打开的所有三个资源。运行上面的代码后,我们得到预期的输出:
Opening resource 0
Opening resource 1
Opening resource 2
Using resources.
Closing resource 2
Closing resource 1
Closing resource 0
Run Code Online (Sandbox Code Playgroud)
如果您必须使用更多资源 -res(0) ... res(10)是否可以使用 for 循环动态生成与下面的伪代码等效的内容?
with res(0), res(1), ... , res(10):
print('Using resources.')
Run Code Online (Sandbox Code Playgroud) 我试图围绕如何编写一个上下文管理器来处理在处理任何异常的同时编写一些日志。我试图解决的问题是编写这样的代码:
try:
# code that can raise exception here
except Exception as e:
print('failed', e)
print('all good')
Run Code Online (Sandbox Code Playgroud)
这是我在代码中的重复模式,我认为最好使用上下文管理器处理,例如:
with my_ctx_manager(success_msg='all good', failed_msg='failed):
# code that can raise exception here
Run Code Online (Sandbox Code Playgroud)
这看起来好多了,但我不知道如何编写实际的上下文管理器来处理可能在上下文中出现的任何异常。
@contextlib.contextmanager
def my_ctx_manager(success_msg, failed_msg):
try:
# if no exception then print(success_msg)
# How do I catch any exception here
except Exception:
print(failed_msg)
# I need the exception to propagate as well
raise
Run Code Online (Sandbox Code Playgroud)
我想我的问题更多是这样的:如何确保上下文管理器正确捕获、记录并重新引发正在包装的代码的任何异常?
这是我基本上要做的事情:
import sh, os
with sh.cd('/tmp'):
print os.getcwd()
print os.getcwd()
Run Code Online (Sandbox Code Playgroud)
我收到以下错误
line 3, in <module>
with sh.cd('/tmp'):
AttributeError: __exit__
Run Code Online (Sandbox Code Playgroud)
我在这里错过了什么?是否有替代解决方案来更改上下文中的目录?
我试图使用python with-statement(也称为上下文管理器)来确保server_socket.accept()始终关闭创建的TCP连接套接字.然而,明显的形式不起作用,因为accept()返回多个值.
有没有办法对具有多个返回值的函数使用with语句?
下面是一个最小的例子,我想使用类似于注释代码的东西来替换try/finally块.
#!/usr/bin/env python3
import socket
from socket import socket as Socket
with Socket(socket.AF_INET, socket.SOCK_STREAM) as server_socket:
server_socket.bind(('', 8011))
server_socket.listen(1)
print("server ready")
while True:
# with server_socket.accept() as (connection_socket, _):
# request = connection_socket.recv(1024).decode('ascii')
# reply = request.upper()
# connection_socket.send(reply.encode('ascii'))
try:
connection_socket, _ = server_socket.accept()
request = connection_socket.recv(1024).decode('ascii')
reply = request.upper()
connection_socket.send(reply.encode('ascii'))
finally:
connection_socket.close()
Run Code Online (Sandbox Code Playgroud)
使用带注释的with语句时的错误消息是:
Traceback (most recent call last):
File "./test.py", line 26, in <module>
with server_socket.accept() as (connection_socket, _):
AttributeError: __exit__
Run Code Online (Sandbox Code Playgroud)
大概这是因为元组没有 …
当我在上下文管理器中引发任何异常时,不会运行清理代码.例如:
from contextlib import contextmanager
try:
raise BaseException()
except BaseException:
print "bye from except"
@contextmanager
def say_goodbye():
yield
print "bye from context manager"
with say_goodbye():
raise BaseException()
Run Code Online (Sandbox Code Playgroud)
将输出:
bye from except
Traceback (most recent call last):
File "", line 15, in
BaseException
Run Code Online (Sandbox Code Playgroud)
请注意,try/except正确捕获异常,而with语句则没有.有什么我不明白如何使用语句?
你可以在这里看到代码:http://pythonfiddle.com/context-manager-failing
仅供我在OSX小牛队运行python 2.7.虽然我已经能够在许多环境中重现,但我怀疑这与它有很大关系.
python exception-handling contextmanager python-2.7 try-except
contextmanager ×10
python ×10
for-loop ×2
python-2.7 ×2
csv ×1
generator ×1
loops ×1
mysql ×1
nested ×1
shell ×1
sockets ×1
sqlite ×1
try-except ×1