python是不是以错误的顺序从swip中删除实例?可以修改吗?
Posted
技术标签:
【中文标题】python是不是以错误的顺序从swip中删除实例?可以修改吗?【英文标题】:does python delete instances from swip in wrong order? Can it be modified?python是否以错误的顺序从swip中删除实例?可以修改吗? 【发布时间】:2017-02-14 14:42:14 【问题描述】:我使用 SWIG 在 c++ 中封装了一些类。我的 python 脚本看起来像
#!/usr/bin/python
import pyinput
import pygeom
import pystate
import pyeqfactory
import pyeigenprobfactory
import pyeigensolver
inp = pyinput.Input("heter1d/1d1g_heter")
geo = pygeom.ProbGeom1D(inp)
state = pystate.State1D(inp, geo);
equation = pyeqfactory.EqFactory1D.New(state)
eigenprob = pyeigenprobfactory.EigenProbFactory1D.New(state, equation)
solver = pyeigensolver.EigenSolver1D(state, eigenprob)
solver.solve_eigenproblem()
print state.get_keff()
我从智能指针类中得到一个错误,因为一个实例在被其他人拥有的同时被删除了
--------------------------------------------------------
An error occurred in line <114> of file </home/segonpin/lib/dealii/source/base/subscriptor.cc> in function
virtual dealii::Subscriptor::~Subscriptor()
The violated condition was:
counter == 0
The name and call sequence of the exception was:
ExcInUse (counter, object_info->name(), infostring)
Additional Information:
Object of class N6dealii13TriangulationILi1ELi1EEE is still used by 1 other objects.
(Additional information: <none>)
See the entry in the Frequently Asked Questions of deal.II (linked to from http://www.dealii.org/) for a lot more information on what this error means and how to fix programs in which it happens.
Stacktrace:
-----------
#0 /home/segonpin/lib/dealii-8.4.bin/lib/libdeal_II.g.so.8.4.2: dealii::Subscriptor::~Subscriptor()
#1 /home/segonpin/lib/dealii-8.4.bin/lib/libdeal_II.g.so.8.4.2: dealii::Triangulation<1, 1>::~Triangulation()
#2 /home/segonpin/codessebas/dealii-neutron-transport/python/_pygeom.so: Forest::ProbGeom<1>::~ProbGeom()
#3 /home/segonpin/codessebas/dealii-neutron-transport/python/_pygeom.so:
#4 python: PyObject_Call
#5 python: PyObject_CallFunctionObjArgs
#6 /home/segonpin/codessebas/dealii-neutron-transport/python/_pygeom.so:
#7 python: ) [0x4fd4e6]
#8 python: PyDict_SetItem
#9 python: _PyModule_Clear
#10 python: PyImport_Cleanup
#11 python: Py_Finalize
#12 python: Py_Main
#13 /lib/x86_64-linux-gnu/libc.so.6: __libc_start_main
#14 python: _start
--------------------------------------------------------
当我以正确的顺序手动删除产生问题的两个类时,错误消失了
#!/usr/bin/python
import pyinput
import pygeom
import pystate
import pyeqfactory
import pyeigenprobfactory
import pyeigensolver
inp = pyinput.Input("heter1d/1d1g_heter")
geo = pygeom.ProbGeom1D(inp)
state = pystate.State1D(inp, geo);
equation = pyeqfactory.EqFactory1D.New(state)
eigenprob = pyeigenprobfactory.EigenProbFactory1D.New(state, equation)
solver = pyeigensolver.EigenSolver1D(state, eigenprob)
solver.solve_eigenproblem()
print state.get_keff()
# these two lines solve the problem
del state
del geo
不应该是python以相同的顺序删除这些实例(因为state
的构造函数中使用了geo
)?谢谢!
编辑 2017 年 2 月 15 日,11:19。
我可以添加一些额外的原因来说明为什么我需要按特定顺序删除。我正在使用 swig 来解析一个 c++ 库(www.dealii.org),当我创建一个需要 A 实例才有意义的 B 实例时,A 中的一个计数器会增加,表示它由 B 拥有。这用于删除对象(B需要A存在,所以我们在删除A之前删除B)。如果您以其他方式执行此操作,则会出现错误。在这种情况下,python 实例包含其中一些依赖项,因此我必须删除特定其他对象中的对象以避免错误消息。
我在 python 析构函数中添加了一些消息
#!/usr/bin/python
import pyinput
import pygeom
import pystate
import pyeqfactory
import pyeigenprobfactory
import pyeigensolver
def deltalk(self):
print type(self).__name__ ," die"
pyinput.Input.__del__ = deltalk
pygeom.ProbGeom1D.__del__ = deltalk
pystate.State1D.__del__ = deltalk
pyeqfactory.EqFactory1D.__del__ = deltalk
pyeigenprobfactory.EigenProbFactory1D.__del__ = deltalk
pyeigensolver.EigenSolver1D.__del__ = deltalk
pypostprocessing.PostProcessing1D.__del__ = deltalk
inp = pyinput.Input("heter1d/1d1g_heter")
geo = pygeom.ProbGeom1D(inp)
state = pystate.State1D(inp, geo);
equation = pyeqfactory.EqFactory1D.New(state)
eigenprob = pyeigenprobfactory.EigenProbFactory1D.New(state, equation)
solver = pyeigensolver.EigenSolver1D(state, eigenprob)
当我运行它时,我发现它并没有按照我需要的方式进行破坏(在 state
之前破坏 geo
在 C++ 中引发错误)
$ python test2_forest.py
EigenSolver1D die
ProbGeom1D die
--------------------------------------------------------
An error occurred in line <114> of file </home/segonpin/lib/dealii/source/base/subscriptor.cc> in function
virtual dealii::Subscriptor::~Subscriptor()
The violated condition was:
counter == 0
The name and call sequence of the exception was:
ExcInUse (counter, object_info->name(), infostring)
Additional Information:
Object of class N6dealii13TriangulationILi1ELi1EEE is still used by 1 other objects.
(Additional information: <none>)
See the entry in the Frequently Asked Questions of deal.II (linked to from http://www.dealii.org/) for a lot more information on what this error means and how to fix programs in which it happens.
Stacktrace:
-----------
#0 /home/segonpin/lib/dealii-8.4.bin/lib/libdeal_II.g.so.8.4.2: dealii::Subscriptor::~Subscriptor()
#1 /home/segonpin/lib/dealii-8.4.bin/lib/libdeal_II.g.so.8.4.2: dealii::Triangulation<1, 1>::~Triangulation()
#2 /home/segonpin/codessebas/dealii-neutron-transport/python/_pygeom.so: Forest::ProbGeom<1>::~ProbGeom()
#3 /home/segonpin/codessebas/dealii-neutron-transport/python/_pygeom.so:
#4 python: PyObject_Call
#5 python: PyObject_CallFunctionObjArgs
#6 /home/segonpin/codessebas/dealii-neutron-transport/python/_pygeom.so:
#7 python: ) [0x4fd4e6]
#8 python: PyDict_SetItem
#9 python: _PyModule_Clear
#10 python: PyImport_Cleanup
#11 python: Py_Finalize
#12 python: Py_Main
#13 /lib/x86_64-linux-gnu/libc.so.6: __libc_start_main
#14 python: _start
考虑到这种依赖性,有没有一种通用的方法告诉 python 删除对象?还是应该在每个类的析构函数中明确说出来?
谢谢
【问题讨论】:
在构造函数中使用并不意味着什么...你保留对另一个对象的引用吗? 嗨@Tali我正在使用swig来解析一个c ++库(www.dealii.org),当我创建一个需要A实例才有意义的B实例时,计数器是在A中增加了它属于B的说法。这是用于删除对象(B需要A存在,所以我们在删除A之前删除B)。如果您以其他方式执行此操作,则会出现错误。在这种情况下,python 实例包含其中一些依赖项,因此我必须删除特定其他对象中的对象以避免错误消息。 【参考方案1】:如果将来有人发现同样的问题,我已经找到了一种方法,可以使用atexit
按我想要的顺序调用删除。
不干净但实用的解决方案
不是很干净,但我会是这样的:
#!/usr/bin/python
import pyinput
import pygeom
import pystate
import pyeqfactory
import pyeigenprobfactory
import pyeigensolver
def goodbye() :
print "Goodbye!!\n"
import atexit
atexit.register(goodbye)
def deltalk(self):
print self.__class__.__name__ ," die"
pyinput.Input.__del__ = deltalk
pygeom.ProbGeom1D.__del__ = deltalk
pystate.State1D.__del__ = deltalk
pyeqfactory.Equation1D.__del__ = deltalk
pyeigenprobfactory.EigenProb1D.__del__ = deltalk
pyeigensolver.EigenSolver1D.__del__ = deltalk
pypostprocessing.PostProcessing1D.__del__ = deltalk
inp = pyinput.Input("heter1d/1d1g_heter")
atexit.register(inp.__del__)
geo = pygeom.ProbGeom1D(inp)
atexit.register(geo.__del__)
state = pystate.State1D(inp, geo);
atexit.register(state.__del__)
equation = pyeqfactory.EqFactory1D.New(state)
atexit.register(equation.__del__)
eigenprob = pyeigenprobfactory.EigenProbFactory1D.New(state, equation)
atexit.register(eigenprob.__del__)
solver = pyeigensolver.EigenSolver1D(state, eigenprob)
atexit.register(solver.__del__)
当我运行脚本时,我得到了
$ python test2_forest.py
EigenSolver1D die
EigenProb1D die
Equation1D die
State1D die
State1D die
ProbGeom1D die
Input die
Goodbye!!
Input die
EigenProb1D die
State1D die
ProbGeom1D die
EigenSolver1D die
Equation1D die
如果可以直接修改构造函数就更好了
如果我可以在构造函数中添加atexit.register
会容易得多,如下例所示
#!/usr/bin/python
import atexit
class Foo(object):
def __init__(self, id):
self.id = id
atexit.register(self.__del__)
def __del__(self):
print(self.id, " says bye")
a = Foo(1)
b = Foo(2)
c = Foo(3)
但是类是用c++定义的,用SWIG解析的,所以我需要修改一个现有类定义的构造函数来做这样的事情,所以对于一个小程序来说手动做起来更容易。
修改现有构造函数...
如果您必须为许多课程这样做,但如果您仍想避免手动注册,这不是最佳选择。类 foo 如下
#simplefoo.py
class Foo(object):
def __init__(self, id):
self.id = id
现有类的构造函数可以修改如下
#test.py
from simplefoo import Foo
# first: I load the module atexit and register the bye function
import atexit
def bye():
print("Bye bye!")
atexit.register(bye)
# second: I add the destructor that talks loudly
def del_ini(self):
print(self.id, " says bye")
Foo.__del__ = del_ini
# third: I modify the original constructor. This is ugly
Foo.ini_old = Foo.__init__
def ini_new(self, id):
self.ini_old(id)
atexit.register(self.__del__)
Foo.__init__ = ini_new
# fourth: I create objects and finish the program them to see what happens
a = Foo(1)
b = Foo(2)
c = Foo(3)
当我们运行脚本时,我们得到
$ python3 test.py
3 says bye
2 says bye
1 says bye
Bye bye!
3 says bye
1 says bye
2 says bye
谢谢。
【讨论】:
以上是关于python是不是以错误的顺序从swip中删除实例?可以修改吗?的主要内容,如果未能解决你的问题,请参考以下文章
100%通过率 华为OD机试 python最小调整顺序次数 2023 Q1 |100分
如何从 Python 列表中删除重复项并保持顺序? [复制]