理解 Python 中的语句和上下文管理器

2025-04-10 09:45:00
admin
原创
15
摘要:问题描述:我正在尝试理解该with语句。我理解它应该替换try/except块。现在假设我做这样的事情:try: name = "rubicon" / 2 # to raise an exception except Exception as e: print("N...

问题描述:

我正在尝试理解该with语句。我理解它应该替换try/except块。

现在假设我做这样的事情:

try:
   name = "rubicon" / 2  # to raise an exception
except Exception as e:
   print("No, not possible.")
finally:
   print("OK, I caught you.")

我如何使用上下文管理器来代替它?


解决方案 1:

contextlib.contextmanager函数装饰器提供了一种方便的方式来提供上下文管理器,而无需编写ContextManager自己的完整类(使用__enter____exit__方法,因此您不必记住__exit__方法的参数,或者方法__exit__必须使用才能抑制异常)。相反,您可以在希望块运行的位置return True编写一个带有单个的函数,然后像平常一样捕获任何异常(实际上来自)。yield`with`yield

from contextlib import contextmanager
@contextmanager
def handler():
    # Put here what would ordinarily go in the `__enter__` method
    # In this case, there's nothing to do
    try:
        yield # You can return something if you want, that gets picked up in the 'as'
    except Exception as e:
        print("no not possible")
    finally:
        print("Ok I caught you")

with handler():
    name='rubicon'/2 #to raise an exception

为什么要费力编写上下文管理器呢?代码重用。您可以在多个地方使用相同的上下文管理器,而不必重复异常处理。如果异常处理是该情况所独有的,那么就不必使用上下文管理器。但如果相同的模式一次又一次出现(或者对于您的用户来说可能如此,例如关闭文件、解锁互斥锁),那么值得付出额外的努力。如果异常处理有点复杂,这也是一个很好的模式,因为它将异常处理与代码流的主线分开。

解决方案 2:

with并没有真正取代try/ except,而是try/ finally。不过,你可以让上下文管理器在异常情况下和非异常情况下执行不同的操作:

class Mgr(object):
    def __enter__(self): pass
    def __exit__(self, ext, exv, trb):
        if ext is not None: print "no not possible"
        print "OK I caught you"
        return True

with Mgr():
    name='rubicon'/2 #to raise an exception

return True部分是上下文管理器决定抑制异常的地方(就像您不在子句中重新引发它一样except)。

解决方案 3:

Pythonwith中的 用于包装一组语句,您可以在其中设置、销毁或关闭资源。try...finally在这方面,它与 finally 子句类似,因为即使在发生异常后也会执行。

上下文管理器是一个实现两种方法的对象:__enter____exit__。它们分别在with块之前和之后被调用。

例如,看一下经典的open()例子:

with open('temp.txt', 'w') as f:
    f.write("Hi!")

Open 返回一个实现或多或少类似和类似的File对象。__enter__`return self__exit__self.close()`

解决方案 4:

上下文管理器的组件

  1. 你应该实现一个返回对象的__enter__方法

  2. 实现exit方法。

例子

我举个简单的例子来说明为什么需要上下文管理器。中国新疆的冬天,开门要立刻关门,如果忘记关门,就会着凉。

 class Door:
     def __init__(self):
         self.doorstatus='the door was closed when you are not at home'
         print(self.doorstatus)
     def __enter__(self):
         print('I have opened the door')
         return self
     def __exit__(self,*args):
         print('pong!the door has closed')
     def fetchsomethings(self):
         print('I have fetched somethings')

回家拿东西的时候,应该打开门,拿东西,然后关门。

 with Door() as dr:
     dr.fetchsomethings()

输出为:

the door was closed when you are not at home
I have opened the door
I have fetched somethings
pong!the door has closed

解释

当你启动一个 Door 类时,它将调用init方法,该方法将打印“当你不在家时门已关闭”,并调用enter方法,该方法将打印“我已打开门”并返回一个名为 dr 的门实例。当在 with 块中调用self.fetchsomethings时,该方法将打印“我已获取某些东西”。当块完成时,上下文管理器将调用exit
方法并打印“pong!门已关闭”。当你不使用 with 关键字时,enterexit将不会被调用!!!!

解决方案 5:

with语句或上下文管理器可以帮助提供资源(尽管可能有更多的用途)。

假设您打开了一个文件进行写入:

f = open(path, "w")

现在您有一个打开的文件句柄。在处理文件期间,没有其他程序可以对其进行写入。为了让其他程序对其进行写入,您必须关闭文件句柄:

f.close()

但是,在关闭文件之前发生了错误:

f = open(path, "w")
data = 3/0  # Tried dividing by zero. Raised ZeroDivisionError
f.write(data)
f.close()

现在将发生的是函数或整个程序将退出,同时留下一个打开的句柄。(CPython 在终止时清理句柄,句柄与程序一起释放,但您不应该依赖这一点)

with 语句确保只要你离开它的缩进,它就会关闭文件句柄:

with open(path, "w") as f:
    data = 3/0  # Tried dividing by zero. Raised ZeroDivisionError
    f.write(data)
# In here the file is already closed automatically, no matter what happened.

with语句可以用于更多用途。例如:threading.Lock()

lock = threading.Lock()
with lock:  # Lock is acquired
   do stuff...
# Lock is automatically released.

几乎所有使用上下文管理器完成的事情都可以用,try: ... finally: ...但是上下文管理器使用起来更方便,更舒适,更易读,并且通过实现__enter____exit__提供易于使用的界面。


创建上下文管理器是通过在普通类中实现__enter__()和完成的。__exit__()

__enter__()告诉当上下文管理器启动时以及当上下文管理器存在时该做什么(如果发生异常,__exit__()则将异常传递给方法)__exit__()

创建上下文管理器的快捷方式可以在contextlib中找到。它将生成器包装为上下文管理器。

解决方案 6:

管理资源:在任何编程语言中,文件操作或数据库连接等资源的使用都非常常见。但这些资源的供应有限。因此,主要问题在于确保在使用后释放这些资源。如果不释放它们,则会导致资源泄漏,并可能导致系统变慢或崩溃。如果用户拥有一种自动设置和拆除资源的机制,那将非常有帮助。在 Python 中,可以通过使用上下文管理器来实现,这有助于正确处理资源。执行文件操作的最常见方式是使用关键字,如下所示:

 # Python program showing a use of with keyword
 with open("test.txt") as f:  
     data = f.read()

打开文件时会消耗文件描述符,这是一种有限的资源。一个进程一次只能打开一定数量的文件。以下程序演示了这一点。

file_descriptors = []
for x in range(100000):
    file_descriptors.append(open('test.txt', 'w'))

它导致错误:OSError: [Errno 24] Too many open files: 'test.txt'

Python 提供了一种管理资源的简单方法:上下文管理器。使用 with 关键字。当它被评估时,它应该产生一个执行上下文管理的对象。上下文管理器可以使用类或函数(带装饰器)编写。

创建上下文管理器:使用类创建上下文管理器时,用户需要确保该类具有以下方法:__enter__()__exit__()__enter__()返回需要管理的资源,__exit__()不返回任何内容但执行清理操作。首先,让我们创建一个名为 ContextManager 的简单类来了解使用类创建上下文管理器的基本结构,如下所示:

# Python program creating a context manager 
class ContextManager():
    def __init__(self):
        print('init method called')
         
    def __enter__(self):
        print('enter method called')
        return self
     
    def __exit__(self, exc_type, exc_value, exc_traceback):
        print('exit method called')
 
with ContextManager() as manager:
    print('with statement block')

Output:
init method called
enter method called
with statement block
exit method called

在这种情况下,将创建一个 ContextManager 对象。它被分配给关键字 ie manager 后的变量。运行上述程序时,将按顺序执行以下操作:

  • __init__()

  • __enter__()

  • 语句主体(with 块内的代码)

  • __exit__()【该方法中的参数用于管理异常】

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   2482  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1533  
  PLM(产品生命周期管理)项目对于企业优化产品研发流程、提升产品质量以及增强市场竞争力具有至关重要的意义。然而,在项目推进过程中,范围蔓延是一个常见且棘手的问题,它可能导致项目进度延迟、成本超支以及质量下降等一系列不良后果。因此,有效避免PLM项目范围蔓延成为项目成功的关键因素之一。以下将详细阐述三大管控策略,助力企业...
plm系统   0  
  PLM(产品生命周期管理)项目管理在企业产品研发与管理过程中扮演着至关重要的角色。随着市场竞争的加剧和产品复杂度的提升,PLM项目面临着诸多风险。准确量化风险优先级并采取有效措施应对,是确保项目成功的关键。五维评估矩阵作为一种有效的风险评估工具,能帮助项目管理者全面、系统地评估风险,为决策提供有力支持。五维评估矩阵概述...
免费plm软件   0  
  引言PLM(产品生命周期管理)开发流程对于企业产品的全生命周期管控至关重要。它涵盖了从产品概念设计到退役的各个阶段,直接影响着产品质量、开发周期以及企业的市场竞争力。在当今快速发展的科技环境下,客户对产品质量的要求日益提高,市场竞争也愈发激烈,这就使得优化PLM开发流程成为企业的必然选择。缺陷管理工具和六西格玛方法作为...
plm产品全生命周期管理   0  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用