Найти - Пользователи
Полная версия: wx.Python, wx.Dialog
Начало » GUI » wx.Python, wx.Dialog
1 2 3
n2b
pyuser
Именно это я Вам и показал, если Вы этого не видите - извините, как показать еще доходчивей - я не знаю.
В Вашем коде коннектион возвращается функцией, а функция открывает коннектион каждый раз, когда к ней обращаешься… А обращаюсь я к connection около 500 раз, получается connection открывается 500 раз и TNS оракловский падает. Мне необходимо обращаться к connection без функции.
pyuser
я уже устал повторять, что в моем псевдокоде connection создается один раз и совсем не важно сколько раз Вы к нему обращаетесь.
n2b
# псевдокод
# --- module mainform.py ---
import createconnection
import newrecord

class MainForm:
def __init__(self):
...
self.db = None
...

def get_connection(self):
if self.db is None:
self.db = createconnection.create_connection() ## Обращение к функции(!!!), которая возвращает connection - т.е. тут открывается коннект к БД
return self.db

def add_record(self):
newrecord.add_record(db)
# --- end module ---

# --- module createconnection.py ---
class Connection:
# пользователь вводит все необходимое для создания подключения
...
def create_connection():
connection = None
dlg = Connection()
if wx.ID_OK == dlg.ShowModal():
connection = # создаем подключение ## подключение создается в теле функции(!!!) create_connection(), т.е. каждый раз при обращении к этой функции будет открываться новый connection!!!!
## А коннект создается следующим образом:
connection = cx_Oracle.connect(scott/tiger@orcl)
##или
cx_Oracle.connect(scott/tiger@server:1521/orcl)
dlg.Destroy()
return connection ## Возращение connection, это разве не функция?
# --- end module ---

# --- module newrecord.py ---
class NewRecord:
# пользователь вводит все необходимое
...
## зачем тут вводить пользователю ЕЩЕ РАЗ все данные? Он же их ввел в классе Connection!
def add_record(db):
dlg = NewRecord()
if wx.ID_OK == dlg.ShowModal():
## Здесь нужен connection и опять мы будем делать так:
connection = createconnection.create_connection() ## Здесь еще одно обращение к функции которая возвращает connection - соответственно открывается ЕЩЕ ОДИН коннектион. А такх обращений к функции будет около 200-300, т.е. обращение к функции откроет еще один коннектион и на 50ом обращении TNS сервер рухнет.
rs = db.cursor()
rs.execute("INSERT ....")
db.commit()
dlg.Destroy()
# --- end module ---
Показал в комментариях (мои комментарии это две #).
Piton23
лол а зачем использовать
createconnection.create_connection()
в module newrecord.py в функции add_record?? (строка 47 )
Зачем тогда туда аргумент db передавать если вы его не используете а создаете новое подключение.

PS в MainForm в методе add_record, вызов функции вроде б неправильный
либо так newrecord.add_record(self.get_connection())
либо хотя б так newrecord.add_record(self.db)
Хотя первый вариант мне кажется более правильный, т.к. не всегда знаешь че там лежит в db
n2b
# -*- coding: windows-1251 -*- 
import wx
import db
import msgbox
import cx_Oracle
class db_info(wx.Dialog):
def __init__(self):
# инициализация
style=wx.FRAME_TOOL_WINDOW | wx.CLOSE_BOX
wx.Dialog.__init__(self, None, -1, style=style, title='Информация для присоединения к базе',
size=(100,200))
wx.Dialog.SetFocus(self)

#panel = wx.Panel(self, -1)
# Атрибуты
login = wx.StaticText(self, -1, "Login:", pos=(1,1))
self.loginTxt = wx.TextCtrl(self, -1, "artur", pos=(1,15))
tns = wx.StaticText(self, -1, "TNS:", pos=(1,40))
self.tnsTxt = wx.TextCtrl(self, -1, "orcl", pos=(1,55))
self.loginTxt.SetInsertionPoint(0)
passw = wx.StaticText(self, -1, "Password:", pos=(1,80))
self.passwTxt = wx.TextCtrl(self, -1, "123", pos=(1,100),
style=wx.TE_PASSWORD)

# Кнопки
self.ConnectBtn = wx.Button(self, wx.ID_OK, "Присоединится", pos=(1, 125))
self.Bind(wx.EVT_BUTTON, self.OnConnectBtn, self.ConnectBtn)
self.ConnectBtn.SetDefault()

self.CancelBtn = wx.Button(self, wx.ID_CANCEL, "Отмена", pos=(2, 150))
self.Bind(wx.EVT_BUTTON, self.OnCancelBtn, self.CancelBtn)

# Получаем данные для покдлючения

def OnConnectBtn(self, event):
global dblogin, dbpass, dbtns
dblogin = (self.loginTxt.GetValue())
dbpass = (self.passwTxt.GetValue())
dbtns = (self.tnsTxt.GetValue())
self.Close()

def dbdata(self):
dbdata = (dblogin, dbpass, dbtns)
return dbdata

def OnCancelBtn(self, event):
self.Destroy()

# Та самая функция из псевдо-кода для открытия одного единственного

def create_connection():
connection = None
dlg = db_info()
if wx.ID_OK == dlg.ShowModal(): # данная строка окрывает диалог подключения, что вообще не нужно, но суть не в этом.
connection = cx_Oracle.connect("%s/%s@%s" % (dblogin, dbpass, dbtns))
dlg.Destroy()
return connection
А теперь обращаемся к этой функции:
connection = db_info.create_connection()
print connection
Получаем - None.
Почему? Потому что все что я ввожу в форме диалога подключения к базе, а именно переменные: dblogin, dbpass, dbtns испаряются вместе с закрытием диалога. Я не понимаю почему, это кстати еще один из вопросов которые я хотел задать. Почему переменные живут только пока живет форма, а при закрытии ВСЕ переменные исчезают. Именно поэтому я не могу выцепить self.connection так как она испаряется вместе со всеми переменными… =\ Если бы не испарялись бы, я бы давно уже все сделал в лучшем виде, а щас одних костылей штук 20 из-за этого понаписал…
Piton23
Во первых скиньте весь код, и модель и контроллер (или как там у вас разбито), потому что понять вас когда вы пишете часть кода, потом “Та самая функция из псевдо-кода для открытия одного единственного”. И “А теперь обращаемся к этой функции:” откуда вы обращаетесь я вот не понял.

“Получаем - None.” А вы уверены что строка
connection = cx_Oracle.connect(“%s/%s@%s” % (dblogin, dbpass, dbtns))
вообще выполняется гарантированно. Даже если и выполняется то уверены ли что коннект происходит успешно? Не проще ли сразу прочитать переменную connection и посмотреть там, сразу после создания нормально ли коннектится с данными dblogin, dbpass, dbtns и от туда уже плясать

“так как она испаряется вместе со всеми переменными”
Что за чушь ничего не испаряется. Тем более совет не использовать глобальные переменные. А вместо глобализирования, т.е.:

def OnConnectBtn(self, event):
global dblogin, dbpass, dbtns
dblogin = (self.loginTxt.GetValue())
dbpass = (self.passwTxt.GetValue())
dbtns = (self.tnsTxt.GetValue())
self.Close()

я б лучше записывал в свойства класса db_info и в дальнейшем обращался б к ним в той же функции create_connection (все равно в ней создаете объект класса)

В итоге либо скидывайте весь код и дальше уже смотрим, либо тестируйте и смотрите где у вас ошибки всплывают. А говорить типа код выкладывал выше не надо. Уже он изменился 100500 раз так что какие у вас там новые ошибки возникают это только вам известно.
n2b
Скидываю код как сейчас реализовано, т.е. щас все работает. Но ведь хочется чтобы правильно работало!
data_info:
# -*- coding: windows-1251 -*- 
import wx
import db_info
import msgbox
import db
import log
class data_info(wx.Frame):
def __init__(self, parent=None):
style=wx.DEFAULT_FRAME_STYLE | wx.FRAME_TOOL_WINDOW
wx.Frame.__init__(self, None, -1, style=style, title='Выберите схему и таблицу',
size=(180, 150))
self.panel = wx.Panel(self, -1, pos=(1,1), size=(400, 50))
wx.Frame.Center(self)
wx.Frame.IsActive(self)
wx.Frame.SetFocus(self)

self.dbdata = db_info.db_info().dbdata()
self.schemasList = db.Get_DB_Schemas(self.dbdata[0], self.dbdata[1], self.dbdata[2])
self.Schema = wx.StaticText(self.panel, -1, "Выберите схему:", pos=(1, 1))
self.ChoiceSchema = wx.Choice(self.panel, -1, size=(165,10), pos=(1,20), choices=[i[0] for i in self.schemasList])


self.SelSchema = self.ChoiceSchema.GetStringSelection()
self.tablesList = db.Get_DB_Tables(self.dbdata[0], self.dbdata[1], self.dbdata[2], self.SelSchema)

self.Table = wx.StaticText(self.panel, -1, "Выберите таблицу:", pos=(1,50))
self.ChoiceTable = wx.Choice(self.panel, -1, size=(165,10), pos=(1,70), choices=[i[0] for i in self.tablesList])

self.ChoiceTable.Disable()

self.OKBtn = wx.Button(self.panel, -1, "OK", pos=(1,100))
self.Bind(wx.EVT_BUTTON, self.OnOKBtn, self.OKBtn)
self.OKBtn.Disable()

self.CancelBtn = wx.Button(self.panel, -1, "Отмена", pos=(90,100))
self.Bind(wx.EVT_BUTTON, self.OnCancelBtn, self.CancelBtn)


self.ChoiceSchema.Bind(wx.EVT_CHOICE, self.OnChoiceSchema)
self.ChoiceTable.Bind(wx.EVT_CHOICE, self.OnChoiceTable)


def OnChoiceSchema(self, event):
self.ChoiceTable.Enable()

self.SelSchema = self.ChoiceSchema.GetStringSelection()
#info = (u'Схема: %s' % (self.SelSchema))
#log.wLog(info)

self.tablesList = db.Get_DB_Tables(self.dbdata[0], self.dbdata[1], self.dbdata[2], self.SelSchema)
self.tables=[i[0] for i in self.tablesList]
self.ChoiceTable.SetItems(self.tables)

def OnChoiceTable(self, event):
self.SelTable = self.ChoiceTable.GetStringSelection()
#info = (u'Таблица: %s' % (self.SelTable))
#slog.wLog(info)
self.OKBtn.Enable()

def OnOKBtn(self, event):
global SelTable, SelSchema
SelTable = self.ChoiceTable.GetStringSelection()
SelSchema = self.ChoiceSchema.GetStringSelection()
self.Close()

def OnCancelBtn(self, event):
self.Destroy()

def Get_Table(self):
try:
Table=SelTable
return Table
except NameError, info:
error = "Вы не выбрали таблицу"
msgbox.Error(error)

def Get_Schema(self):
try:
Schema=SelSchema
return Schema
except NameError, info:
error = "Вы не выбрали схему"
msgbox.Error(error)
db_info
# -*- coding: windows-1251 -*- 
import wx
import db
import msgbox
import cx_Oracle
class db_info(wx.Dialog):
def __init__(self):
# инициализация
style=wx.FRAME_TOOL_WINDOW | wx.CLOSE_BOX
wx.Dialog.__init__(self, None, -1, style=style, title='Информация для присоединения к базе',
size=(100,200))
wx.Dialog.SetFocus(self)

#panel = wx.Panel(self, -1)
# Атрибуты
login = wx.StaticText(self, -1, "Login:", pos=(1,1))
self.loginTxt = wx.TextCtrl(self, -1, "artur", pos=(1,15))
tns = wx.StaticText(self, -1, "TNS:", pos=(1,40))
self.tnsTxt = wx.TextCtrl(self, -1, "orcl", pos=(1,55))
self.loginTxt.SetInsertionPoint(0)
passw = wx.StaticText(self, -1, "Password:", pos=(1,80))
self.passwTxt = wx.TextCtrl(self, -1, "123", pos=(1,100),
style=wx.TE_PASSWORD)

# Кнопки
self.ConnectBtn = wx.Button(self, wx.ID_OK, "Присоединится", pos=(1, 125))
self.Bind(wx.EVT_BUTTON, self.OnConnectBtn, self.ConnectBtn)
self.ConnectBtn.SetDefault()

self.CancelBtn = wx.Button(self, wx.ID_CANCEL, "Отмена", pos=(2, 150))
self.Bind(wx.EVT_BUTTON, self.OnCancelBtn, self.CancelBtn)

def OnConnectBtn(self, event):
global dblogin, dbpass, dbtns
dblogin = (self.loginTxt.GetValue())
dbpass = (self.passwTxt.GetValue())
dbtns = (self.tnsTxt.GetValue())
self.connection = db.OpenDB(dblogin, dbpass, dbtns)
self.Close()

def dbdata(self):
dbdata = (dblogin, dbpass, dbtns)
return dbdata

def OnCancelBtn(self, event):
self.Destroy()
data_info - один из модулей где нужна переменная connection
db_info - модуль где форма для ввода данных.

Кстати, функции Get_table и Get_Schema написаны ТОЛЬКО потому что если обращаться к переменной self.SelTable - то эта переменная ТОЖЕ пуста, т.е. выбрал таблицу и схему, нажал ОК, и всё, в любой другой форме где нужна переменная self.SelTable - я не могу к ней обращаться, компилятор пишет что такой переменной НЕТ! А обращаясь к функциям которые я написал, программа почему то опять делает запрос, опять получает весь список таблиц и только потом получает нужную таблицу, почему - тоже не понимаю…

Вот функции из модуля db:
# -*- coding: windows-1251 -*- 
import cx_Oracle
import msgbox
from itertools import chain

def OpenDB(dblogin,dbpass,dbtns):
try:
import cx_Oracle
except ImportError,info:
error = ("Import Error: %s" % (info))
msgbox.Error(error)
exit()

if cx_Oracle.version<'3.0':
error = ("Very old version of cx_Oracle : %s" % (cx_Oracle.version))
msgbox.Error(error)
exit()

try:
connection = cx_Oracle.connect("%s/%s@%s" % (dblogin, dbpass, dbtns))
except cx_Oracle.DatabaseError, info:
error = ("Database Error: %s" % (info))
msgbox.Error(error)
exit()

return connection

def Get_DB_Schemas(dblogin, dbpass, dbtns):
zconnection = cx_Oracle.connect("%s/%s@%s" % (dblogin, dbpass, dbtns))
cursor = cx_Oracle.Cursor(connection)
sql_sel = "select USERNAME from dba_users"
cursor.execute(sql_sel)
schemas = cursor.fetchall()
return schemas
cursor.close()

def Get_DB_Tables(dblogin, dbpass, dbtns, SelSchema):
connection = cx_Oracle.connect("%s/%s@%s" % (dblogin, dbpass, dbtns))
cursor = cx_Oracle.Cursor(connection)
sql = ("select TABLE_NAME from dba_tables WHERE OWNER = '%s'" % (SelSchema))
cursor.execute(sql)
tables = cursor.fetchall()
return tables
cursor.close()

def Get_Data(connection, Table, Schema):
cursor = cx_Oracle.Cursor(connection)
sql = ("select * from %s.%s" % (Schema, Table))
cursor.execute(sql)
data = cursor.fetchall()
cursor.close()
data = list(chain(*data))
data = len(data)
return data
Piton23
Чет новое наклепали, то что не работает явно видимо удалили, вот зачем только, к примеру где реализации class NewRecord и def add_record(db) и т.п. Ну да ладно все не выставили дело ваше.


n2b
если обращаться к переменной self.SelTable - то эта переменная ТОЖЕ пуста, т.е. выбрал таблицу и схему, нажал ОК, и всё, в любой другой форме где нужна переменная self.SelTable - я не могу к ней обращаться, компилятор пишет что такой переменной НЕТ!
Я тоже кстати не нашел этой переменной, нигде не объявляется, нигде не используется. Где вы ее ранее используете ранее не вижу.


n2b
Кстати, функции Get_table и Get_Schema написаны
Написаны но криво. Вам ж тысячи раз говорили использовать существующее соединение а не делать новое, зачем

n2b
connection = cx_Oracle.connect(“%s/%s@%s” % (dblogin, dbpass, dbtns))
производить коннект заново? Вам же советовали использовать через класс и доставить через метод соединение (get_connection):


pyuser
class MainForm:
def __init__(self):

self.db = None


def get_connection(self):
if self.db is None:
self.db = createconnection.create_connection()
return self.db
n2b
т.е. щас все работает
Правильно работает, часть не работоспособного кода по удаляли небось вот и работает.
PS. Никогда не удаляйте, а комментируйте, пока не будете уверены что программа на 100% доделана
n2b
ээээ, нет.
Никакого неработоспособного кода я не удалял. Всё что вы мне советовали - я изменял свой рабочий код на советы как сделать 1 коннектион вместо того чтобы создавать несколько.
Piton23
вот зачем только, к примеру где реализации class NewRecord и def add_record(db) и т.п. Ну да ладно все не выставили дело ваше.
Тот псевдо код был написан из фантазии автора кода, т.е. к моему коду не имеет НИКАКОГО отношения. Просто как примеры.
Вот я выложил код где создает коннект, все функции использующие коннект и модуль где необходимо его использовать.
Поможите мне юзать один коннект на все случаи когда он нужен, а не как у меня, когда я его создаю. И еще, по поводу функций Get_Table и Get_Schema - где Вы тут увидели создание нового коннекта? Новый конект создается на целый модуль. И ответьте на вопрос пожалуйста, почему когда я обращаюсь к функции Get_Table он заного посылает запрос к базе и получает ВЕСЬ список схем и только после этого отдает мне мою таблицу?
Piton23
Простите, чет не внимательно просмотрел data_info (точнее скопировал), и не видел методов, Get_Table, Get_Schema, перепутал в общем Get_Table с Get_DB_Tables, а Get_Schema с Get_DB_Schemas. И я никак не мог понять зачем в этих методах (а именно в Get_DB_Tables, Get_DB_Schemas) создавать новое подключение а не использовать имеющееся.

А теперь по порядку. У вас форма, где вы вводите данные таблицы, схемы, утверждали что

n2b
если обращаться к переменной self.SelTable - то эта переменная ТОЖЕ пуста, т.е. выбрал таблицу и схему, нажал ОК, и всё, в любой другой форме где нужна переменная self.SelTable - я не могу к ней обращаться, компилятор пишет что такой переменной НЕТ!
т.е. вы делали не
SelTable = self.ChoiceTable.GetStringSelection()
SelSchema = self.ChoiceSchema.GetStringSelection()

а делали их свойствами, т.е.
self.SelTable = self.ChoiceTable.GetStringSelection()
self.SelSchema = self.ChoiceSchema.GetStringSelection()

И вот здесь мне самое интересное, откуда вы обращались к этой переменной (в каком модуле, каком классе(если так), в каком модуле) и как вы к ней обращались, т.е. что было до SelTable. Мне не понятно как она мб пуста.

Могу предположить что вы обращались из Get_Table, Get_Schema к этой переменной. И я надеюсь что вы обращались как self.SelTable а не просто SelTable. Если так то я не могу поверить что там пусто, скиньте скрин тогда уж.


n2b
И ответьте на вопрос пожалуйста, почему когда я обращаюсь к функции Get_Table он заного посылает запрос к базе и получает ВЕСЬ список схем и только после этого отдает мне мою таблицу?
Почему заново посылает запрос к базе?, насколько понял Get_Table возвращает строку выбранной таблицы в форме ранее, т.е. SelTable. Мб что то другое стало инициатором запроса к базе, но никак не Get_Table, там только пере направление строки. И уберите эти глобальные переменные, используйте свойства класса.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB