Форум сайта python.su
pyuserВ Вашем коде коннектион возвращается функцией, а функция открывает коннектион каждый раз, когда к ней обращаешься… А обращаюсь я к connection около 500 раз, получается connection открывается 500 раз и TNS оракловский падает. Мне необходимо обращаться к connection без функции.
Именно это я Вам и показал, если Вы этого не видите - извините, как показать еще доходчивей - я не знаю.
Офлайн
я уже устал повторять, что в моем псевдокоде connection создается один раз и совсем не важно сколько раз Вы к нему обращаетесь.
Офлайн
# псевдокод
# --- 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 ---
Офлайн
лол а зачем использовать
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
Офлайн
# -*- 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.” А вы уверены что строка
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 раз так что какие у вас там новые ошибки возникают это только вам известно.
Офлайн
Скидываю код как сейчас реализовано, т.е. щас все работает. Но ведь хочется чтобы правильно работало!
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)
# -*- 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()
# -*- 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
Отредактировано (Янв. 7, 2012 01:59:13)
Офлайн
Чет новое наклепали, то что не работает явно видимо удалили, вот зачем только, к примеру где реализации class NewRecord и def add_record(db) и т.п. Ну да ладно все не выставили дело ваше.
n2bЯ тоже кстати не нашел этой переменной, нигде не объявляется, нигде не используется. Где вы ее ранее используете ранее не вижу.
если обращаться к переменной self.SelTable - то эта переменная ТОЖЕ пуста, т.е. выбрал таблицу и схему, нажал ОК, и всё, в любой другой форме где нужна переменная self.SelTable - я не могу к ней обращаться, компилятор пишет что такой переменной НЕТ!
n2bНаписаны но криво. Вам ж тысячи раз говорили использовать существующее соединение а не делать новое, зачем
Кстати, функции Get_table и Get_Schema написаны
n2bпроизводить коннект заново? Вам же советовали использовать через класс и доставить через метод соединение (get_connection):
connection = cx_Oracle.connect(“%s/%s@%s” % (dblogin, dbpass, dbtns))
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Правильно работает, часть не работоспособного кода по удаляли небось вот и работает.
т.е. щас все работает
Офлайн
ээээ, нет.
Никакого неработоспособного кода я не удалял. Всё что вы мне советовали - я изменял свой рабочий код на советы как сделать 1 коннектион вместо того чтобы создавать несколько.
Piton23Тот псевдо код был написан из фантазии автора кода, т.е. к моему коду не имеет НИКАКОГО отношения. Просто как примеры.
вот зачем только, к примеру где реализации class NewRecord и def add_record(db) и т.п. Ну да ладно все не выставили дело ваше.
Офлайн
Простите, чет не внимательно просмотрел 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 - я не могу к ней обращаться, компилятор пишет что такой переменной НЕТ!
n2bПочему заново посылает запрос к базе?, насколько понял Get_Table возвращает строку выбранной таблицы в форме ранее, т.е. SelTable. Мб что то другое стало инициатором запроса к базе, но никак не Get_Table, там только пере направление строки. И уберите эти глобальные переменные, используйте свойства класса.
И ответьте на вопрос пожалуйста, почему когда я обращаюсь к функции Get_Table он заного посылает запрос к базе и получает ВЕСЬ список схем и только после этого отдает мне мою таблицу?
Офлайн