Взаимодействие между модулями / классами в wxPython
У меня есть задача по переносу многопользовательского проекта VBA с большим количеством взаимодействий с базами данных во что-то другое - поскольку это должно быть чем-то, что не может требовать установки программного обеспечения (поэтому JRE и.NET исключены). Я считаю, что это можно сделать с Python - wxPython покрывает фреймы и различные элементы управления (я использую boa-конструктор для его конструктора фреймов), мне также удалось подключиться через adodbapi к текущей базе данных, используемой VBA. Я просто отстой в том, чтобы все сложить правильно. Рассмотрим этот скелет:
myApp.py
#!/usr/bin/env python
#Boa:App:BoaApp
import wx
import myFrame
modules ={u'myFrame': [1, 'Main frame of Application', u'myFrame.py']}
class BoaApp(wx.App):
def OnInit(self):
# here I think I'd see something like, say:
# self.main.cnnObject = adodbapi.connect ( some proper connection string )
self.main = myFrame.create(None)
self.main.Show()
self.SetTopWindow(self.main)
return True
def main():
application = BoaApp(0)
application.MainLoop()
if __name__ == '__main__':
main()
myFrame.py
#Boa:Frame:myFrame
import wx
def create(parent):
return myFrame(parent)
[wxID_MYFRAME, wxID_MYFRAMEBUTTON1,
] = [wx.NewId() for _init_ctrls in range(2)]
class myFrame(wx.Frame):
def _init_ctrls(self, prnt):
# generated method, don't edit
wx.Frame.__init__(self, id=wxID_MYFRAME, name='myFrame', parent=prnt,
pos=wx.Point(710, 329), size=wx.Size(400, 250),
style=wx.DEFAULT_FRAME_STYLE, title='MainFrame')
self.SetClientSize(wx.Size(392, 223))
self.button1 = wx.Button(id=wxID_MYFRAMEBUTTON1,
label='FETCH cnnObject', name='button1', parent=self,
pos=wx.Point(0, 144), size=wx.Size(392, 79), style=0)
self.button1.Bind(wx.EVT_BUTTON, self.OnButton1,
id=wxID_MYFRAMEBUTTON1)
def __init__(self, parent):
self._init_ctrls(parent)
def OnButton1(self, event):
event.Skip()
# here and in other events in other frames I would like to retrieve
# that cnnObject to use for queries
Добавление множества элементов управления, событий, открытие последовательных фреймов из этого и следующего, похоже, работает. Однако, чтобы не приходилось копировать / вставлять все содержимое соединения с базой данных снова и снова, я хотел, чтобы все было в одном месте и просто получал доступ к этому коду из фреймов. Моя общая идея состоит в том, что, поскольку существует только один объект myApp, он может содержать объект подключения, тем более что строка подключения будет доступна как sys.argv[1]. Возможно ли это? И если да, то как бы я сослался на объект приложения внутри метода OnButton1? Также есть шанс, что я все понял неправильно, и в этом случае я хотел бы услышать схему "правильного пути". Я чувствую, что мне может не хватать, возможно, подходящей оболочки класса для этих операций с базой данных, но даже если я ее сделаю, мне все равно хотелось бы иметь только один экземпляр этого класса во всех моих будущих фреймах, но я не могу даже удается сделать это с помощью экземпляра приложения - я импортирую myApp в myFrame (что само по себе кажется странным, поскольку myApp уже импортирует myFrame, так что в обоих направлениях?), но независимо от того, какой тип присвоения локальной переменной я пытаюсь, я в основном получаю " у объекта 'module' нет атрибута " ... (что заставляет меня думать, что я, вероятно, не понимаю, как работают области видимости / модули в Python)
1 ответ
Я написал немного об этом, но я использовал SQLAlchemy. Это была моя первая попытка:
Затем я получил комментарии и помощь от друга из сообщества wxPython и разработчиков SQLAlchemy и немного обновил приложение:
Эта вторая статья показывает, как создать сеанс базы данных и передать его. Я думаю, что это подход, который вы ищете. Я бы сделал подключение к базе данных в методе init вашего фрейма верхнего уровня:
def __init__(self):
"""Constructor"""
wx.Frame.__init__(self, None, title="Databases!")
self.data_connection = self.create_connection()
Затем, когда вы создаете другие кадры, вы можете передать им это соединение:
def create_new_frame(self):
""""""
new_frame = MyOtherFrame(self.data_connection)
new_frame.Show()
Вот один из способов, которым вы можете настроить класс фреймов:
########################################################################
class MyOtherFrame(wx.Frame):
""""""
#----------------------------------------------------------------------
def __init__(self, data_connection):
"""Constructor"""
wx.Frame.__init__(self, None, title="Other frame")
self.data_connection = data_connection
Просто убедитесь, что вы не закрываете соединение для передачи данных в другом кадре, поскольку это также закроет его в исходном кадре верхнего уровня.
Это решение также относится к вашему вызову OnButton1. Просто измените это так:
def OnButton1(self, event):
cursor = self.data_connection.cursor()
Вы заметите, что вы можете получить доступ к self.data_connection в любом месте вашего основного фрейма, потому что он был определен как переменная уровня класса.
Вы также можете быть заинтересованы в проекте Dabo, который является оболочкой для wxPython, которая должна облегчить работу с базами данных: http://www.dabodev.com/