python是否以错误的顺序从swip中删除实例?可以修改吗?

2024-03-28 13:08:49 发布

您现在位置:Python中文网/ 问答频道 /正文

我用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不应该以相同的顺序删除这些实例(因为geostate的构造函数中使用)?谢谢!你知道吗


编辑:2017年2月15日11:19。你知道吗

我可以添加一些额外的理由,说明为什么我需要按特定顺序删除。我正在使用swig解析一个c++库(www.dealii.org),当我创建一个需要一个A实例来解释的B实例时,计数器会增加,表示它属于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引发c++错误之前销毁geo

$ 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删除对象?或者我应该在每个类的析构函数中显式地说它?你知道吗

谢谢


Tags: ofinimporthomebinlibgeostate
1条回答
网友
1楼 · 发布于 2024-03-28 13:08:49

万一将来有人发现同样的问题,我已经找到了一种方法,用atexit按我想要的顺序调用delete。你知道吗

不干净但功能性解决方案

它不是很干净,但我会是这样的:

#!/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

谢谢。你知道吗

相关问题 更多 >