我使用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
不应该以相同的顺序删除这些实例(因为geo
在state
的构造函数中使用)?谢谢!
编辑2017年2月15日,11:19。
我可以添加一些额外的理由,说明为什么我需要按特定顺序删除。我正在使用swig来解析c 库(www.dealii.org),当我创建一个需要a实例的B实例时,就会增加一个计数器。这用于删除对象(B需要a存在,因此我们在删除a之前删除b)。如果您以其他方式这样做,则会遇到错误。在这种情况下,Python实例包含其中一些依赖项,因此我必须在特定其他方面删除对象,以避免错误消息。
我在Python Destructor
中添加了一些消息#!/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考虑考虑此依赖性的对象?还是我应该在每个班级的破坏者中明确说出来?
谢谢
如果有人在将来找到同样的问题,我找到了一种以我想要使用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
谢谢。