I'm developing a python program to monitor and control a game-server. The game-server has many game-cores, and those cores handle the clients.
I have a python class called Server
that holds instances of the class Core
, and those instances are used to manage the actual game-cores. The Core
class needs to connect to the game-core via TCP-Socket, in order to send commands to that specific game-core. To close those sockets properly, the Core
class has a __del__
method which closes the socket.
An example:
class Server(object):
Cores = [] # list which will be filled with the Core objects
def __init__(self):
# detect the game-cores, create the core objects and append them to self.Cores
class Core(object):
CoreSocket = None # when the socket gets created, the socket-object will be bound to this variable
def __init__(self, coreID):
# initiate the socket connection between the running game-core and this python object
def __del__(self):
# properly close the socket connection
Now, when I use the Core
class itself, the destructor always gets called properly. But when I use the Server
class, the Core
objects inside Server.Cores
never get destructed. I have read that the gc has a problem with circular references and classes with destructors, but the Core
objects never reference the Server
object (only the socket-object, in Core.CoreSocket
), so no circular references are created.
I usually prefer using the with
-statement for resource cleaning, but in this case I need to send commands over many different methods in the Server
class, so using with
won't help ... I also tried to create and close the socket on each command, but that really kills the performance when I need to send many commands. Weak refereneces created with the weakref
module won't help eigther, because the destructors then get called immediately after I create the Server
object.
Why don't the Core
objects get destructed properly when the Server
object gets cleaned up by the gc? I guess I'm just forgetting something simple, but I just can't find out what it is.
Or maybe there is a better approach for closing those sockets when the object gets cleaned up?
You've mixed up class and instance members. Unlike in some other languages, defining a variable at class scope creates a class variable, not an instance variable. When a
Server
instance dies, theServer
class is still around and still holds references to the cores. Defineself.cores
in the__init__
method instead: