Ответ 1
Нормальная сильная ссылка AKA - это та, которая поддерживает живой объект: в CPython каждый объект хранит количество (нормальных) ссылок на него (известное как "счетчик ссылок" или RC) и уходит как только RC достигнет нуля (случайная метка поколений и прокручивание также собирает "опорные петли" для сбора мусора ").
Если вы не хотите, чтобы объект оставался в живых только потому, что к нему относится другой, тогда вы используете "слабую ссылку", специальную разновидность ссылок, которая не увеличивает RC; Подробнее см. документы. Конечно, поскольку упомянутый объект CAN удаляется, если не упоминается иначе (вся цель слабого ref, а не нормального!), Ссылающийся на объект должен быть предупрежден, если он пытается использовать объект что ушло - и это предупреждение дается именно за исключением того, что вы видите.
В вашем коде...:
def __init__(self,dbname):
tmp = sqlite.connect(dbname)
self.con = tmp.cursor()
def __del__(self):
self.con.close()
tmp
является нормальной ссылкой на соединение... но это локальная переменная, поэтому она уходит в конце __init__
. Указатель (особенно названный;-) cursor self.con
остается, но он внутренне реализован, чтобы удерживать WEAK ref для соединения, поэтому соединение исчезает, когда tmp
делает. Таким образом, в __del__
вызов .close
завершается с ошибкой (поскольку курсор должен использовать соединение, чтобы закрыть его).
Простейшим решением является следующее крошечное изменение:
def __init__(self,dbname):
self.con = sqlite.connect(dbname)
self.cur = self.con.cursor()
def __del__(self):
self.cur.close()
self.con.close()
Я также воспользовался возможностью использовать con для подключения и cur для курсора, но Python не будет возражать, если вы заинтересованы в их замене (вы просто оставите читателей недоумевающими; -).