假设您有三个通过上下文管理器获取的对象,例如A锁,数据库连接和ip套接字.您可以通过以下方式获取它
with lock:
with db_con:
with socket:
#do stuff
Run Code Online (Sandbox Code Playgroud)
但有没有办法在一个街区内完成?就像是
with lock,db_con,socket:
#do stuff
Run Code Online (Sandbox Code Playgroud)
此外,如果有一组具有上下文管理器的未知长度的对象,是否有可能以某种方式做到:
a=[lock1, lock2, lock3, db_con1, socket, db_con2]
with a as res:
#now all objects in array are acquired
Run Code Online (Sandbox Code Playgroud)
如果答案是"不",是不是因为需要这样的功能意味着设计不好,或者我应该建议它?:-P
这可能会把事情推得太远,但主要是出于好奇.
是否有可能以具有一个可调用的对象(功能/类)充当两个上下文管理器,并在同一时间装饰器:
def xxx(*args, **kw):
# or as a class
@xxx(foo, bar)
def im_decorated(a, b):
print('do the stuff')
with xxx(foo, bar):
print('do the stuff')
Run Code Online (Sandbox Code Playgroud) 我发现我在Python中使用了大量的上下文管理器.但是,我一直在测试使用它们的一些东西,我经常需要以下内容:
class MyTestCase(unittest.TestCase):
def testFirstThing(self):
with GetResource() as resource:
u = UnderTest(resource)
u.doStuff()
self.assertEqual(u.getSomething(), 'a value')
def testSecondThing(self):
with GetResource() as resource:
u = UnderTest(resource)
u.doOtherStuff()
self.assertEqual(u.getSomething(), 'a value')
Run Code Online (Sandbox Code Playgroud)
当这得到很多测试时,这显然会变得无聊,所以本着SPOT/DRY的精神(单点真相/不要重复自己),我想将这些位重构为测试setUp()和tearDown()方法.
然而,试图这样做会导致这种丑陋:
def setUp(self):
self._resource = GetSlot()
self._resource.__enter__()
def tearDown(self):
self._resource.__exit__(None, None, None)
Run Code Online (Sandbox Code Playgroud)
必须有更好的方法来做到这一点.理想情况下,在每个测试方法的setUp()/ tearDown()不重复位中(我可以看到如何重复每个方法上的装饰器可以做到这一点).
编辑:将底层对象视为内部GetResource对象,将对象视为第三方对象(我们不会更改).
我已经重命名GetSlot为GetResourcehere-这比特定情况更通用 - 其中上下文管理器是对象打算进入锁定状态的方式.
我有一些带遗留函数的遗留代码,它将文件名作为参数并处理文件内容.下面是代码的工作传真.
我想要做的是不必使用我生成的一些内容写入磁盘以使用此遗留函数,因此我可以使用StringIO创建对象来代替物理文件名.但是,这不起作用,如下所示.
我认为StringIO是这样的方式.任何人都可以告诉我是否有一种方法可以使用这个遗留函数并在参数中传递一些东西,而不是磁盘上的文件但可以通过遗留函数对待它?遗留函数确实让with上下文管理器对filename参数值进行处理.
我在谷歌遇到的一件事是:http://bugs.python.org/issue1286,但这对我没有帮助......
码
from pprint import pprint
import StringIO
# Legacy Function
def processFile(filename):
with open(filename, 'r') as fh:
return fh.readlines()
# This works
print 'This is the output of FileOnDisk.txt'
pprint(processFile('c:/temp/FileOnDisk.txt'))
print
# This fails
plink_data = StringIO.StringIO('StringIO data.')
print 'This is the error.'
pprint(processFile(plink_data))
Run Code Online (Sandbox Code Playgroud)
产量
这是输出FileOnDisk.txt:
['This file is on disk.\n']
Run Code Online (Sandbox Code Playgroud)
这是错误:
Traceback (most recent call last):
File "C:\temp\test.py", line 20, in …Run Code Online (Sandbox Code Playgroud) 看起来像做以下事情是很自然的:
with socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
Run Code Online (Sandbox Code Playgroud)
但Python没有为socket实现上下文管理器.我可以轻松地将其用作上下文管理器,如果是,如何使用?
我熟悉使用python的with语句作为在抛出异常时确保对象完成的一种方法.这通常看起来像
with file.open('myfile.txt') as f:
do stuff...
Run Code Online (Sandbox Code Playgroud)
这是短手的
f = file.open('myfile.txt'):
try:
do stuff...
finally:
f.close()
Run Code Online (Sandbox Code Playgroud)
或者一个班级可能出现的其他任何终结例程.
我最近遇到了一段处理OpenGL的代码:
with self.shader:
(Many OpenGL commands)
Run Code Online (Sandbox Code Playgroud)
请注意,没有任何as关键字.这是否表明,__enter__和__exit__之类的方法仍然被调用,但该对象从未明确地在块使用(即,它是通过全局或隐含引用)?还是有一些其他意义在逃避我?
使用时遇到此错误pool.map(funct, iterable):
AttributeError: __exit__
Run Code Online (Sandbox Code Playgroud)
否解释,只将堆栈跟踪到模块中的pool.py文件.
以这种方式使用:
with Pool(processes=2) as pool:
pool.map(myFunction, mylist)
pool.map(myfunction2, mylist2)
Run Code Online (Sandbox Code Playgroud)
我怀疑可挑选性可能存在问题(python需要pickle,或将列表数据转换为字节流)但我不确定这是否属实或是否如何调试.
编辑:产生此错误的新格式代码:
def governingFunct(list):
#some tasks
def myFunction():
# function contents
with closing(Pool(processes=2)) as pool:
pool.map(myFunction, sublist)
pool.map(myFunction2, sublist2)
Run Code Online (Sandbox Code Playgroud)
错误产生:
PicklingError: Can't pickle <type 'function'>: attribute lookup __builtin__.function failed
Run Code Online (Sandbox Code Playgroud) 有时我需要一个无效的虚拟上下文管理器.然后,它可以用作更有用但可选的上下文管理器的替身.例如:
ctx_mgr = <meaningfulContextManager> if <condition> else <nullContextManager>
with ctx_mgr:
...
Run Code Online (Sandbox Code Playgroud)
如何定义这样一个简单的空上下文管理器?Python库是否提供现成的?
我们希望将上下文与as子句一起使用的情况如何?
with ctx_mgr as resource:
<operations on resource>
Run Code Online (Sandbox Code Playgroud) 我有一个异步API,我用它连接并发送邮件到SMTP服务器,它有一些设置和拆除它.所以它很适合使用contextmanagerPython 3的contextlib.
虽然,我不知道它是否可能写,因为它们都使用生成器语法来编写.
这可能会证明问题(包含yield-base和async-await语法的混合,以演示异步调用和上下文管理器的收益之间的差异).
@contextmanager
async def smtp_connection():
client = SMTPAsync()
...
try:
await client.connect(smtp_url, smtp_port)
await client.starttls()
await client.login(smtp_username, smtp_password)
yield client
finally:
await client.quit()
Run Code Online (Sandbox Code Playgroud)
目前python中有可能出现这种情况吗?with as如果是,我将如何使用声明?如果没有,我可以用另一种方式实现这一点 - 也许使用旧式上下文管理器?
我希望将数据库事务的逻辑封装到一个with块中; 将代码包装在事务中并处理各种异常(锁定问题).这很简单,但是我想让块在某些异常后封装代码块的重试.我无法看到一种方法将它整齐地打包到上下文管理器中.
是否可以在with语句中重复代码?
我想像它一样使用它,这真的很整洁.
def do_work():
...
# This is ideal!
with transaction(retries=3):
# Atomic DB statements
...
...
Run Code Online (Sandbox Code Playgroud)
我目前正在使用装饰器处理它,但我更愿意提供上下文管理器(或实际上两者),所以我可以选择在with块中包含几行代码而不是包装在装饰器中的内联函数,这就是我现在所做的:
def do_work():
...
# This is not ideal!
@transaction(retries=3)
def _perform_in_transaction():
# Atomic DB statements
...
_perform_in_transaction()
...
Run Code Online (Sandbox Code Playgroud) contextmanager ×10
python ×10
asynchronous ×1
decorator ×1
pickle ×1
python-2.x ×1
sockets ×1
unit-testing ×1