Python 对象生命周期特征

2024-06-22

注意:如果您知道任何(非详细的)库代码可以实现我想要的功能,请启发 C/C++ 程序员,我会接受它作为答案。

我有一个全局变量设置为以下类的实例。它的目的是允许我设置一些手动中断点来放置一些快速和肮脏的东西printfscrapy 蜘蛛中的样式调试点(当满足某些条件来调整解析器时,我特别需要中断,有一些极其罕见的输入数据异常)——改编自this http://docs.python.org/faq/library#id12.

操作系统是 OS X 10.8。

import termios, fcntl, sys, os

class DebugWaitKeypress(object):
    def __init__(self):
        self.fd = sys.stdin.fileno()
        self.oldterm = termios.tcgetattr(self.fd)
        self.newattr = termios.tcgetattr(self.fd)
        self.newattr[3] = self.newattr[3] & ~termios.ICANON & ~termios.ECHO
        termios.tcsetattr(self.fd, termios.TCSANOW, self.newattr)

        self.oldflags = fcntl.fcntl(self.fd, fcntl.F_GETFL)
        fcntl.fcntl(self.fd, fcntl.F_SETFL, self.oldflags | os.O_NONBLOCK)

    def wait(self):
        sys.stdin.read(1)

    def __del__(self):
        print "called del"
        termios.tcsetattr(self.fd, termios.TCSAFLUSH, self.oldterm)
        fcntl.fcntl(self.fd, fcntl.F_SETFL, self.oldflags)

当我按 Ctrl-C 并且进程正在展开时,出现以下异常:

Exception AttributeError: "'NoneType' object has no attribute 'tcsetattr'" in <bound method DebugWaitKeypress.__del__ of <hon.spiders.custom_debug.DebugWaitKeypress object at 0x108985e50>> ignored

我猜我遗漏了一些关于对象生命周期机制的内容?如何补救这种情况。据我所知,任何类实例都应该在导入代码之前被销毁,不是吗?按照声明/定义的相反顺序。

如果进程退出后终端没有搞砸,我会忽略这一点:D

edit:

Delian 对 seth 答案的评论让我明白我需要使用 Cmain()像函数,或作为根函数占主导地位并初始化那里的上下文的任何其他函数/生成器。这样当进程下降时__exit__将调用上下文管理器的方法。我不必重新编程每个终端流wait() call.

尽管重新编程的成本可能并不重要,但了解如何在 Python 中使用这些基本的 C/C++ 语义还是很有好处的。

edit 2:

当弄乱标准输入时,Twisted(scrapy 使用的)会变得很糟糕。所以我必须用文件IO来解决问题。


长话短说:__del__对于此目的毫无用处(以及几乎任何其他目的;您可能应该忘记它的存在)。如果您想要确定性清理,请使用上下文管理器。

据我所知,任何类实例都应该在导入代码之前被销毁,不是吗?按照声明/定义的相反顺序。

那是C++。忘了它。 Python 并不关心这一点,事实上它甚至不关心大多数需要做的事情。整个Python语言中不存在声明这样的东西,模块级变量存储在本质上是无序关联数组中。变量不存储对象,它们存储引用(即notC++ 引用,它们基本上是没有指针算术的指针)——对象位于堆上,并且不知道有关变量、绑定、语句或语句顺序的信息。

此外,当对象被垃圾收集时,并且是否完全被GC,未定义。你得到一个mostly由于引用计数,CPython 中的确定性图片是确定性的,但即使如此,它也会在出现循环时下降。结果就是__del__可以在任何时间点调用(包括当模块的一半已经被拆除时)或根本不调用。多个对象定义__del__互相引用也很麻烦,尽管有些 GC 努力做正确的事情。

底线是,你当时可以假设的东西很少__del__运行,所以你不能做太多事情。您可以最后一次处理那些本应通过其他方法清理但没有清理的资源,仅此而已。经验法则:Never依靠它anything强制的。

相反,创建一个上下文管理器并通过以下方式使用它with http://docs.python.org/py3k/reference/compound_stmts.html#the-with-statement。您可以获得确定性的清理,而不必担心对象的生命周期。因为,说实话,对象生命周期和资源生命周期是两个完全不同的东西,并且只在 C++ 中纠缠在一起,因为它是进行资源管理的最佳方式在那个环境下。在 Python 中,RAII 不适用,而是这样:

with <context manager> as var:
    # do something
# "context closed", whatever that means - for resources, usually cleanup

顺便说一句,您可以通过更方便地定义它上下文库 http://docs.python.org/py3k/library/contextlib.html#contextlib.contextmanager(从您的版本快速音译,可能包含错误或丑陋):

from contextlib import contextmanager


@contextmanager
def debug_wait_keypress():
    fd = sys.stdin.fileno()
    oldterm = termios.tcgetattr(fd)
    newattr = termios.tcgetattr(fd)
    newattr[3] = newattr[3] & ~termios.ICANON & ~termios.ECHO
    termios.tcsetattr(fd, termios.TCSANOW, newattr)
    oldflags = fcntl.fcntl(fd, fcntl.F_GETFL)
    fcntl.fcntl(fd, fcntl.F_SETFL, oldflags | os.O_NONBLOCK)
    try:
        yield
    finally:
        termios.tcsetattr(fd, termios.TCSAFLUSH, oldterm)
        fcntl.fcntl(fd, fcntl.F_SETFL, oldflags)

Your wait方法成为自由函数。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Python 对象生命周期特征 的相关文章

随机推荐

  • IIS 6 上的 elmah

    我有一个网站 上面运行着 elmah 记录到一个 sql 框 在我的测试环境中 它是一台 IIS 7 机器 一切运行良好 当我上传到运行 IIS 6 的网络解决方案 Web 时 出现错误 SecurityException Request
  • 在 x86-64 多核机器上以 C++ Atomic 读取和写入 int

    我读了this https stackoverflow com questions 5002046 atomicity in c myth or reality 我的问题很相似但又有些不同 请注意 我知道 C 0x 不能保证这一点 但我特别
  • 将 yyyy-mm-dd 转换为 dd mm yyyy

    如何将 2013 06 24 转换为 2013 年 6 月 24 日 我正在使用下面的代码 date1 2013 06 24 SimpleDateFormat d new SimpleDateFormat dd MMM yyyy try d
  • Cordova 不创建 AndroidManifest.xml

    我正在 Cordova 和 AndroidStudio 中创建 Android iOS 应用程序 一切都工作正常 直到我昨天将 Cordova 更新到 8 我还将 Node 更新到了最新版本 当我创建 Cordova 项目并添加 Andro
  • 如何使用 Java 10、Ant 和 Eclipse 编译器编译此代码?

    我正在尝试使用 Java 10 Ant 和 Eclipse 编译器编译这个简单的代码 import java util ArrayList import javax xml bind JAXBException class Test voi
  • 伊2。动态添加属性和规则到模型

    我正在编写一个小部件 我想避免用户向他们的模型添加代码 我知道这会更容易 但用它来学习新东西 您是否知道是否可以向模型添加一个属性 该属性不在您的数据库中 因此它将是虚拟的 并为该属性添加规则 您无权更改该模型代码 我知道规则是一个数组 过
  • Clojure:如何生成“trie”?

    鉴于以下 def inTree 1 2 1 2 3 1 2 4 5 9 1 2 4 10 15 1 2 4 20 25 你如何将它转换成这个特里树 def outTrie 1 2 3 4 5 9 10 15 20 25 这是一个清理后的解决
  • JaCoCo 和 MR 罐子

    JaCoCo 有一个问题 并且多版本 JAR 文件 http openjdk java net jeps 238 由于两个地方存在相同的类名 JaCoCo 抱怨道 Caused by java lang IllegalStateExcept
  • 每次 iPhone App 重新启动时 NSHomeDirectory 返回不同的路径

    我注意到每次我用 Xcode 重新启动应用程序时 NSHomeDirectory 都会返回不同的路径 显然即使我手动单击图标 因为它不会加载文件的内容 我很惊讶每次重新启动应用程序时它都会给我一个不同的目录 即使我使用 ForUser 方法
  • 为什么我的页面可以在 IE9 的 IE7 模式下工作,但不能在 IE7 本身下工作?

    在对 IE9 的每种浏览器和文档模式进行了大量测试之后 我最近启用了我们的新主页 not只是兼容模式 但实际的 IE7 和 IE8 仿真 该网站可以在每种模式下运行 更不用说现代浏览器了 然而 在它推出后 我收到一封电子邮件 说该网站在 I
  • 从书签加载外部 JS?

    如何使用书签加载外部 JavaScript 文件 这将克服 IE 的 URL 长度限制 并且通常会保持简洁 2015年更新 内容安全政策 https developer mozilla org en US docs Web Security
  • 模板模板部分特化仅与 -std=c++1z 和 g++ 一起使用

    我发现下面这段代码 include
  • 更新通用列表中元素的最佳方法[重复]

    这个问题在这里已经有答案了 假设我们有一个名为 Dog 的类 它有两个字符串 Name 和 Id 现在假设我们有一个包含 4 只狗的列表 如果您想更改 Id 为 2 的狗的名称 最好的方法是什么 Dog d1 new Dog Fluffy
  • 如何解决出现 python 扩展加载和扩展激活失败消息的问题?

    打开 VS code 时 我不断在屏幕右下角收到这些消息 关于如何摆脱它有什么想法吗 我仍然可以编写代码并运行代码 但我不明白为什么会发生这种情况 我尝试删除 python 扩展以及视频扩展选项卡中与 python 相关的任何内容 但没有成
  • 使用反射设置嵌套属性值

    我已经进行了彻底搜索 但找不到我的问题的确切答案 以下面的代码为例 public class Company private string m strName private Customer m objCustomer public Co
  • 一个解决方案中有多少个项目算太多?

    单个解决方案中有多少个项目是可以接受的 对于那些项目数量较大的应用程序 您是否将其他已编译的 dll 放在某个公共文件夹中以便能够运行该应用程序 由于在 Visual Studio 中项目会编译为程序集 因此您应该问自己的问题是 我应该有多
  • 仅使用 FPC 的 GUI

    我想知道如何在不使用Delphi语言 Object Pascsl 的情况下 仅使用安装了Lazarus的FPC Pascal 来开发GUI应用程序 32位 谢谢 直接使用小部件集 看看例如unix 的 packages gtk2 中的示例
  • CMake:编译 OpenCV 时未找到 CUDA 库

    我正在 Windows 上使用 CMAKE 编译支持 CUDA 的 OpenCV 3 0 0 当我点击 配置 时 出现如下错误 CMake Error The following variables are used in this pro
  • .NET 的多线程库

    我在一些程序中使用了多线程 但仍然感觉不太舒服 有哪些适用于 C NET 的多线程库 其中一个库相对于另一个库有哪些优势 我所说的多线程库是指所有有助于使多线程编程变得更容易的东西 您定期使用什么 NET 集成 例如 ThreadPool
  • Python 对象生命周期特征

    注意 如果您知道任何 非详细的 库代码可以实现我想要的功能 请启发 C C 程序员 我会接受它作为答案 我有一个全局变量设置为以下类的实例 它的目的是允许我设置一些手动中断点来放置一些快速和肮脏的东西printfscrapy 蜘蛛中的样式调