Python 将上下文管理器与系统资源一起使用是否有错误?

Python 将上下文管理器与系统资源一起使用是否有错误?,python,with-statement,Python,With Statement,试图在更深的层次上理解事物 如果我正在打开文件、web请求、tensorflow会话或任何可以用with语句处理的内容;是否有过我不应该在语句中使用的时候 例如,有没有一次我应该使用更通用/通用的try结构,除了之外 我真正的问题是,和真正做的事情的底层结构是什么?我也读了一些不错的书,但对我来说,的一些内部工作似乎有点像黑魔法。我试图揭开神奇组件的神秘面纱。我总是去Python增强建议(PEP)了解Python中的概念,因为与文档相比,它们更关注事物的概念推理,通常直接解决: 新功能/更改的

试图在更深的层次上理解事物

如果我正在打开文件、web请求、tensorflow会话或任何可以用
with
语句处理的内容;是否有过我不应该在
语句中使用
的时候

例如,有没有一次我应该使用更通用/通用的
try
结构,除了
之外


我真正的问题是,
真正做的事情的底层结构是什么?我也读了一些不错的书,但对我来说,
的一些内部工作似乎有点像黑魔法。我试图揭开神奇组件的神秘面纱。

我总是去Python增强建议(PEP)了解Python中的概念,因为与文档相比,它们更关注事物的概念推理,通常直接解决:

  • 新功能/更改的原因
  • 如何使用现有代码/如何影响现有代码
由于您对实施方面感兴趣,这里有一个相关的例子:

规范:“with”语句 建议使用以下语法编写一个新语句:

with EXPR as VAR:
    BLOCK
(省略段落-与此问题无关)

上述声明的译文如下:

mgr = (EXPR)
exit = type(mgr).__exit__  # Not calling it yet
value = type(mgr).__enter__(mgr)
exc = True
try:
    try:
        VAR = value  # Only if "as VAR" is present
        BLOCK
    except:
        # The exceptional case is handled here
        exc = False
        if not exit(mgr, *sys.exc_info()):
            raise
        # The exception is swallowed if exit() returns true
finally:
    # The normal and non-local-goto cases are handled here
    if exc:
        exit(mgr, None, None, None)

因此with语句的内部工作方式与try:finally类似,只是使用了更简洁的语法,使得更难忘记关闭文件等。

有理由不使用with语句:如果失败/成功需要自定义清理

通常,您不需要知道在处理完文件后应该执行哪些清理。
with
-语句负责在任何情况下关闭文件(除了Python没有机会进入contextmanager的
\uuuuuuuuuuuuuuuuu
方法的情况,例如突然关闭系统或类似的异常情况)

但是,如果您需要执行一些本地和重要的清理,那么使用
try/except/finally
可能更有意义。此上下文中的一个重要关键字是:

假设您调用了一个函数,该函数假设创建了一个不由pythonsgc管理的对象,然后打开一个文件并尝试将其写入一个文件。在这种情况下,您需要执行更多的清理,而不仅仅是打开和关闭文件:

def func():
    bad_object = create_object_that_cannot_be_cleaned_by_pythons_gc():
    try:
        with open(filename, 'w') as file:
            file.write(bad_object.to_string())
    finally:
        bad_object.delete()

我真的很难想出一个例子,在这个例子中,使用
try/finally
而不是仅仅创建一个contextmanager是有好处的,我不确定我是否成功(通常我会将这个例子实现为contextmanager:-)。重要的部分应该是ContextManager执行默认的清理操作,而不是本地化的自定义清理。

with
具有
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu进入
方法,这有利于打开和关闭内容。例如,您不会将其用于异常处理,这就是
try/except/..
块更有用的地方。我想这更多的是关于
finally:
部分。是的:如果您使用的python版本没有
with
,那么您应该使用
try:finally
来代替。听起来您在寻找描述
with
语句的代码有效。如果您正在打开一个文件,那么在系统资源方面使用
with
的AFAIK可能会更好,因为您的文件总是在阻塞后关闭,如果您单独使用
open()
而忘记使用
close(),则可能无法释放的系统资源将被释放
文件对象。我很确定这就是
\uu del\uu
方法的作用,因此当对象被垃圾收集时,它会运行一个过程来清理它的资源。我想知道一个更好的例子是否是清理不一定总是相同的,比如,如果我想在文件末尾写入某个字符串,而不考虑其他写入内容,那么在
finally
块中肯定更有意义,而不是它自己的上下文管理器。(除非我经常这样做,否则我会让经理来处理)谢谢,@MSeifert!你很难找到一个例子,这有助于回答我的问题。听起来这种情况非常罕见,我可以安全地忽略它们,当我处理非常奇怪的对象时,重新考虑一下。太棒了!这正是我要找的,但似乎找不到。谢谢@Tadhg。