析构函数和异常 [英] Destructors and exceptions

查看:89
本文介绍了析构函数和异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

大家好


我在测试一些RAII概念时发现了一些有趣的东西

从Python中移植到C ++中。我没有在网上找到任何关于它的信息

,因此这篇文章。


问题是当引发异常时,

当地人的破坏似乎被推迟到程序退出。我错过了什么?b $ b某事?这种行为是设计的吗?如果是这样,有什么理由

吗?我能想到的唯一理由就是加快例外处理; b
处理;但是由于这种方法打破了许多安全编程习惯用语,我认为这是一个糟糕的交易。


以下是有问题的代码:


------------------------------------------ < br $>
类Foo:

def __init __(自我):

print" - foo%s created" %id(self)

def __del __(self):

print" - foo%s destroyed" %id(self)


def normal_exit():

print" normal_exit starts"

x = Foo()

print" normal_exit ends"


def premature_exit():

print" premature_exit starts"

x = Foo()

返回0

打印" premature_exit结束>

def exceptional_exit():

print" exceptional_exit starts"

x = Foo()

raise" oops"

print" exceptional_exit ends"


if __name__ ==" __ main __":

print" main block starts"

try:

normal_exit()

premature_exit()

exceptional_exit()

除外:

print" exception" ;

打印主要块结束

-------------------------- ----------------


我得到的输出是:


---- ------------------------------------ -

主街区开始

normal_exit开始

--foo 141819532创建

normal_exit结束

--foo 141819532销毁

premature_exit开始

--foo 141819532创建

--foo 141819532销毁

exceptional_exit开始

--foo 141819532创建

例外

主要块结束

--foo 141819532销毁

----------------------------------------- -


....这告诉我,只有在程序退出时才会破坏
exceptional_exit()中的本地。肯定它会在提出异常时发生
吗?


问候

David Turner

Hi all

I noticed something interesting while testing some RAII concepts
ported from C++ in Python. I haven''t managed to find any information
about it on the web, hence this post.

The problem is that when an exception is raised, the destruction of
locals appears to be deferred to program exit. Am I missing
something? Is this behaviour by design? If so, is there any reason
for it? The only rationale I can think of is to speed up exception
handling; but as this approach breaks many safe programming idioms, I
see it as a poor trade.

Here is the code in question:

------------------------------------------
class Foo:
def __init__(self):
print "--foo %s created" % id(self)
def __del__(self):
print "--foo %s destroyed" % id(self)

def normal_exit():
print "normal_exit starts"
x = Foo()
print "normal_exit ends"

def premature_exit():
print "premature_exit starts"
x = Foo()
return 0
print "premature_exit ends"

def exceptional_exit():
print "exceptional_exit starts"
x = Foo()
raise "oops"
print "exceptional_exit ends"

if __name__ == "__main__":
print "main block starts"
try:
normal_exit()
premature_exit()
exceptional_exit()
except:
print "exception"
print "main block ends"
------------------------------------------

The output I get is:

------------------------------------------
main block starts
normal_exit starts
--foo 141819532 created
normal_exit ends
--foo 141819532 destroyed
premature_exit starts
--foo 141819532 created
--foo 141819532 destroyed
exceptional_exit starts
--foo 141819532 created
exception
main block ends
--foo 141819532 destroyed
------------------------------------------

....which indicates to me that the destruction of the local in
exceptional_exit() only happens when the program exits. Surely it
should occur at the point at which the exception is raised?

Regards
David Turner

推荐答案



" David Turner" < DK ****** @ telkomsa.net>在留言中写道

新闻:e2 ************************** @ posting.google.c om ...

"David Turner" <dk******@telkomsa.net> wrote in message
news:e2**************************@posting.google.c om...
问题是,当引发异常时,
本地人的破坏似乎被推迟到程序退出。我错过了什么?
The problem is that when an exception is raised, the destruction of
locals appears to be deferred to program exit. Am I missing
something?




当对象的最后一次引用消失时,解释器*可能*但是

是*不需要*忘记或破坏对象,如果确实概念

是有意义的。发生的是依赖于实现的。 CPython通常会立即清理,这比Jython更快。我不确定

人类口译员的做法。写一次,永不擦除对象的存储

(保持对所创建对象的完整审计跟踪)也是合法的。


如果你想强制解决问题,给你的类一个接近的方法,就像

文件对象一样,并明确地调用它。然后在try:finally:中编码,这是为此目的设计的



尝试:

流程

最后:

清理


Terry J. Reedy




When the last reference to an object disappears, the interpreter *may* but
is *not required* to forget or destruct the object, if indeed the concept
is meaningful. What happens is implementation dependent. CPython usually
cleans up immediately, which is sooner than with Jython. I am not sure
what human interpreters do. Write once, never erase storage of objects
(keeping a complete audit trail of objects created) would also be legal.

If you want to force the issue, give your class a close method, as with
file objects, and call it explicitly. Then code in try:finally:, which is
designed for this purpose.
try:
process
finally:
cleanup

Terry J. Reedy





" David Turner" < DK ****** @ telkomsa.net>在留言中写道

新闻:e2 ************************** @ posting.google.c om ...

"David Turner" <dk******@telkomsa.net> wrote in message
news:e2**************************@posting.google.c om...

问题是,当引发异常时,
本地人的破坏似乎被推迟到程序退出。我错过了吗?这种行为是设计的吗?如果是这样,有什么理由吗?我能想到的唯一理由是加快异常处理;但是由于这种方法打破了许多安全编程习惯用语,我认为这是一个糟糕的交易。
The problem is that when an exception is raised, the destruction of
locals appears to be deferred to program exit. Am I missing
something? Is this behaviour by design? If so, is there any reason
for it? The only rationale I can think of is to speed up exception
handling; but as this approach breaks many safe programming idioms, I
see it as a poor trade.



没有Python等价的C ++'s'析构函数保证是在范围退出时调用

,原因有两个:范围退出只会破坏

对象的引用,而不是对象本身;对象的破坏是留给垃圾收集器的b $ b,你对它没有任何影响。特别是

,gc不需要释放资源,因此终结者(最接近C ++的析构函数的终结者)可能无法被调用。这意味着

__del__几乎没用(AFAIMC),并且你不能依赖它们在程序退出之前调用

(或者就此而言)。


我同意,除了try-finally之外,Python没有办法做你提供的b $ b $使代码更难以阅读。一个

新的说明符,例如scoped,将是Python的必需添加:

解释器将保证在

范围退出时调用范围对象的__del__,并在尝试时引发异常别名。


Oliver


There is no Python equivalent of C++''s "destructor garanteed to be called
upon scope exit", for a couple of reasons: scope exit only destroys
references to objects, not the objects themselves; destruction of objects is
left to the garbage collector and you have no influence on it. In
particular, the gc is not required to release resources, so finalizers (the
__del__ method, closest to C++''s destructor) may not get called. This means
__del__ is pretty much useless (AFAIMC), and you can''t rely on them being
called before program exit (or ever, for that matter).

I agree, it is a real pitty that Python doesn''t have a way of doing what you
mention, other than try-finally, which makes code more difficult to read. A
new specifier, e.g. "scoped", would be a required addtion to Python:
interpreter would garantee that __del__ of scoped objects would be called on
scope exit, and raise an exception if attempt to alias.

Oliver



如果你想强迫问题,给你的类一个接近的方法,就像
文件对象一样,并明确地调用它。然后编写try:finally:,这是为此目的而设计的。
尝试:
进程终于:
清理
If you want to force the issue, give your class a close method, as with
file objects, and call it explicitly. Then code in try:finally:, which is
designed for this purpose.
try:
process
finally:
cleanup




这真是太遗憾了。 "最后"当然容易受到健忘的程序员的影响。综合征。它还使用我认为是实现细节的代码来污染代码 - 例如,必须关闭

文件的事实是文件对象的特征,只有

意外地与_use_文件相关。如果能够保证至少那些具有__del__方法的对象的确定性破坏,那么Python将是一种更强大的语言。任何人都可以指出

出于任何技术原因为什么这样的功能不应该包含在

语言中?


无论如何,我想知道是否有另一种解决问题的方法

的资源管理。或许类似Ruby的东西

关闭?有什么建议?必须有一些更优雅的东西(更安全!)而不是终于。


问候

David Turner



That''s a great shame. "Finally" is of course susceptible to the
"forgetful programmer" syndrom. It also pollutes the code with what I
consider to be implementation details -- for example, the fact that a
file must be closed is a characteristic of the file object, and only
accidentally relevant to the _use_ of files. Python would be a much
stronger language if it could guarantee deterministic destruction of
at least those objects which have a __del__ method. Can anyone point
out any technical reasons why such a feature should not be included in
the language?

At any rate, I wonder if there is an another solution to the problem
of resource management. Perhaps something along the lines of Ruby
closures? Any suggestions? There has to be something more elegant
(and safer!) than "finally".

Regards
David Turner


这篇关于析构函数和异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆