Найти - Пользователи
Полная версия: PyQt4 | 2 ошибки в работе программы с БД (из-за исключений)?
Начало » GUI » PyQt4 | 2 ошибки в работе программы с БД (из-за исключений)?
1 2
Kyrym
Бьюсь уже долго, никак не пойму в чём проблема.

1. (решено) В функции “def basa_save” программа берёт значения из полей и при помощи функции с исключениями “def in_ch_f” должна сделать значения вещественными числами, а в случае ошибки превратить их в нули (борьба с пустыми ячейками). Потом модифицированные значения полей попадают в список и в базу данных.
Однако, почему-то модифицируется лишь одно значение, остальные обращаются в ноль. В соседней теме я выкладывал подобную механику с двумя полями - всё работало, а тут болты.
2. (решено) Вообще здесь должна быть база городов. Каждый город попадает в список городов и в общий список с городами и свойствами:
db =  [['Москва', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 
['Питер', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]
db_goroda = ['Москва', 'Питер']
Запись по каждому городу уникальна, т.е. не должно быть двух одинаковых городов, однако, почему-то не срабатывает вот это исключение:
         # проверка - новый город?
        try: # город есть в базе
            gorod_index = db_goroda.index(gorod)
            db[gorod] = db_i
            print('try')
        except:
            print('except')
            db_goroda.append(gorod)
            db_goroda.sort()            
            db.append(db_i)
            db.sort()
            self.box_gorod.addItem(db_i[0])
        # конец: проверка - новый город?
Подскажите, пожалуйста, что у меня не так?
Вот весь код:
 # Python 3. PyQt4
# -*- coding: utf-8 -*-
import sys
import pickle
from PyQt4 import QtGui, QtCore
# БАЗА ДАННЫХ
try:
    F_R = open('db_goroda.pkl', 'rb')
    db = pickle.load(F_R)
    db_goroda = pickle.load(F_R)
except:
    db = []
    db_goroda = []
# ЦВЕТА ПОЛЕЙ
sss_vivod = ("background-color: #456173; color: #f2f2f0; font: 14pt 'Courier New'")
        
# ГРАФИКА
class Window(QtGui.QWidget): # Класс Window  наследует класс QWidget
    def __init__(self, parent=None, *args, **kwargs): # Создаёт конструктор класса, parent - ссылка на родительский эл-т
        QtGui.QWidget.__init__(self, parent)
        super().__init__(parent, QtCore.Qt.Window)
        
        self.setMinimumSize(400, 400) # Ширина и высота окна
        self.resize(600, 600) # шир / выс окна
        self.setWindowTitle('Города') # Заголовок
        self.setWindowIcon(QtGui.QIcon('icon.png')) # Иконка
        # БЛОК СОЗДАНИЯ FRAME
        self.frame_1 = QtGui.QFrame()
        self.frame_1.setFrameShape(1)
        self.frame_1_lay = QtGui.QGridLayout(self.frame_1)
        # БЛОК СОЗДАНИЯ LABEL
        self.lbl_name = QtGui.QLabel('<center><h2>Города</h2></center>')
              
        # БЛОК СОЗДАНИЯ ПОЛЕЙ
        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Preferred)
        self.pole_vivod = QtGui.QTextEdit('')
        self.pole_vivod.setStyleSheet(sss_vivod)
        
        self.pole_resul = QtGui.QTextEdit('')
        self.pole_resul.setStyleSheet(sss_vivod)
        # БЛОК СОЗДАНИЯ КНОПОК
        self.button_open_isd = QtGui.QPushButton('Print БД')     
        self.button_open_isd.clicked.connect(self.on_open_isd)      
       
        self.button_otchet_txt = QtGui.QPushButton('Отчёт в txt')
        self.button_otchet_txt.clicked.connect(self.saveToFile_txt)
        
        self.button_hlp = QtGui.QPushButton('Справка')
        
        # БЛОК СОЗДАНИЯ РАСКРЫВАЮЩЕГОСЯ СПИСКА
        self.box_gorod = QtGui.QComboBox()
        self.box_gorod.addItems(db_goroda)
        self.box_gorod.setCurrentIndex(0)
        self.box_gorod.setAutoCompletion(1) # варианты, подстановка
        self.box_gorod.activated[str].connect(self.on_start)
        self.box_1 = QtGui.QComboBox()
        self.box_1.addItems(['---','a1','a2','a3'])
        self.box_2 = QtGui.QComboBox()
        self.box_2.addItems(['---','b1','b2','b3'])        
        self.box_3 = QtGui.QComboBox()
        self.box_3.addItems(['---','c1','c2','c3'])
        self.box_4 = QtGui.QComboBox()
        self.box_4.addItems(['---','d1','d2','d3'])
        
        # БЛОК РАЗМЕТКИ      
        self.vbox_os = QtGui.QVBoxLayout()
        self.vbox_os.addWidget(self.lbl_name)
        self.hbox_1 = QtGui.QHBoxLayout()
        self.hbox_1.addWidget(self.button_open_isd)
        self.hbox_1.addWidget(self.button_otchet_txt)
        self.hbox_1.addWidget(self.button_hlp)
        self.grid = QtGui.QGridLayout() # создание сетки
        self.grid.setSpacing(5)
        # >>> ФРЕЙМ 1
        m = 6 # всего столбцов
        m1 = 5 # столбцов справа
        self.grid.addWidget(self.frame_1, 0,0,1,m)        
        # ---
        self.lbl_gorod = QtGui.QLabel("▼ ▼ ▼   Выбор города   ▼ ▼ ▼",
                                      alignment=QtCore.Qt.AlignCenter)
        self.frame_1_lay.addWidget(self.lbl_gorod, 1,0,1,m)        
        self.frame_1_lay.addWidget(self.box_gorod, 2,0,1,m)
        self.pole_gorod = QtGui.QLineEdit()
        self.pole_gorod.setPlaceholderText('Новый город')
        self.frame_1_lay.addWidget(self.pole_gorod, 3,0,1,m)
        # ---
        self.frame_1_lay.addWidget(self.box_1, 4,0)
        self.lbl_klr = QtGui.QLabel("- район")
        self.frame_1_lay.addWidget(self.lbl_klr, 4,1,1,m1)
        # ---
        self.frame_1_lay.addWidget(self.box_2, 5,0)
        self.lbl_snr = QtGui.QLabel("- район")
        self.frame_1_lay.addWidget(self.lbl_snr, 5,1,1,m1)
        # ---
        self.frame_1_lay.addWidget(self.box_3, 6,0)
        self.lbl_vtr = QtGui.QLabel("- район")
        self.frame_1_lay.addWidget(self.lbl_vtr, 6,1,1,m1)
        # ---
        self.pole_ssv = QtGui.QLineEdit()
        self.frame_1_lay.addWidget(self.pole_ssv, 7,0)        
        self.lbl_ssv = QtGui.QLabel("- характеристика")
        self.frame_1_lay.addWidget(self.lbl_ssv, 7,1,1,m1)
        # ---
        self.frame_1_lay.addWidget(self.box_4, 8,0)
        self.lbl_glr = QtGui.QLabel("- район")
        self.frame_1_lay.addWidget(self.lbl_glr, 8,1,1,m1)
        # -----------------------
        # ---
        self.lbl_t_1_1 = QtGui.QLabel("парам:")
        self.frame_1_lay.addWidget(self.lbl_t_1_1, 9,0,1,m)
        # ---
        self.pole_t_1_2 = QtGui.QLineEdit()
        self.frame_1_lay.addWidget(self.pole_t_1_2, 10,0)
        self.lbl_t_1_2 = QtGui.QLabel("- 0.98")
        self.frame_1_lay.addWidget(self.lbl_t_1_2, 10,1)
        self.pole_t_1_3 = QtGui.QLineEdit()
        self.frame_1_lay.addWidget(self.pole_t_1_3, 10,2)
        self.lbl_t_1_3 = QtGui.QLabel("- 0.92")
        self.frame_1_lay.addWidget(self.lbl_t_1_3, 10,3)
        # ---
        self.lbl_t_2_1 = QtGui.QLabel("парам:")
        self.frame_1_lay.addWidget(self.lbl_t_2_1, 11,0,1,m)
        # ---
        self.pole_t_2_2 = QtGui.QLineEdit()
        self.frame_1_lay.addWidget(self.pole_t_2_2, 12,0)
        
        self.lbl_t_2_2 = QtGui.QLabel("- 0.98")
        self.frame_1_lay.addWidget(self.lbl_t_2_2, 12,1)        
        self.pole_t_2_3 = QtGui.QLineEdit()
        self.frame_1_lay.addWidget(self.pole_t_2_3, 12,2)
        self.lbl_t_2_3 = QtGui.QLabel("- 0.92")
        self.frame_1_lay.addWidget(self.lbl_t_2_3, 12,3)        
        # ---
        self.lbl_sr_name = QtGui.QLabel("Парам:",
                                      alignment=QtCore.Qt.AlignCenter)
        self.frame_1_lay.addWidget(self.lbl_sr_name, 13,0,1,m)
        # ---
        self.lbl_sr_1 = QtGui.QLabel("1 - янв:", alignment=QtCore.Qt.AlignCenter)
        self.frame_1_lay.addWidget(self.lbl_sr_1, 14,0)
        self.lbl_sr_2 = QtGui.QLabel("2 - февр:", alignment=QtCore.Qt.AlignCenter)
        self.frame_1_lay.addWidget(self.lbl_sr_2, 14,1)
        self.lbl_sr_12 = QtGui.QLabel("12 - дек:", alignment=QtCore.Qt.AlignCenter)
        self.frame_1_lay.addWidget(self.lbl_sr_12, 14,2)
        self.lbl_sr_13 = QtGui.QLabel("Год:", alignment=QtCore.Qt.AlignCenter)
        self.frame_1_lay.addWidget(self.lbl_sr_13, 14,3)
        
        # ---
        self.pole_sr_1 = QtGui.QLineEdit('')
        self.frame_1_lay.addWidget(self.pole_sr_1, 15,0)
        self.pole_sr_2 = QtGui.QLineEdit('')
        self.frame_1_lay.addWidget(self.pole_sr_2, 15,1)
        self.pole_sr_12 = QtGui.QLineEdit('')
        self.frame_1_lay.addWidget(self.pole_sr_12, 15,2)
        self.pole_sr_13 = QtGui.QLineEdit('')
        self.frame_1_lay.addWidget(self.pole_sr_13, 15,3)
        # >>> КОНЕЦ ФРЕЙМА 1
        self.lbl_gost = QtGui.QLabel("пурум")
        self.grid.addWidget(self.lbl_gost, 2,0,1,6)        
                
        self.grid.setColumnMinimumWidth(0,100)
        self.grid.setColumnMinimumWidth(1,100)
        self.grid.setColumnMinimumWidth(2,100)
        self.grid.setColumnMinimumWidth(3,100)
        self.grid.setColumnStretch(0, 0)
        self.grid.setColumnStretch(1, 1)
        self.grid.setRowStretch(10, 1) # поднимает вверх №-индекса строку
        
        # --- БЛОК ПРОКРУТКИ
        self.scrollArea = QtGui.QScrollArea(self)
        self.scrollArea.setWidgetResizable(True) # разрешаем прокрутку
        self.scrollArea.setBackgroundRole(QtGui.QPalette.Midlight)
        self.viewport = QtGui.QWidget()
        self.viewport.setSizePolicy(QtGui.QSizePolicy.Expanding,QtGui.QSizePolicy.Expanding)
        
        self.viewport.setLayout(self.grid) # viewport в
        self.scrollArea.setWidget(self.viewport)
        # --- КОНЕЦ БЛОКА ПРОКРУТКИ
        # >>> УПРАВЛЯЮЩИЕ КНОПКИ
        self.hbox_2 = QtGui.QHBoxLayout()
        # ---
        self.btn_clear = QtGui.QPushButton('Сбросить')
        self.hbox_2.addWidget(self.btn_clear)
        self.btn_clear.clicked.connect(self.on_clear)
        # ---
        self.btn_edit = QtGui.QPushButton('Редактировать')
        self.btn_edit.setCheckable(1) # 2 состояния нажатия
        self.hbox_2.addWidget(self.btn_edit)
        self.btn_edit.clicked.connect(self.on_edit)        
        # ---
        self.btn_save = QtGui.QPushButton('Сохранить')
        self.hbox_2.addWidget(self.btn_save)
        self.btn_save.clicked.connect(self.basa_save)
        # >>> КОНЕЦ УПРАВЛЯЮЩИЕ КНОПКИ
        self.vbox_os.addLayout(self.hbox_1) # кнопки меню
        self.vbox_os.addWidget(self.scrollArea)
        self.vbox_os.addLayout(self.hbox_2)
        self.setLayout(self.vbox_os) # установка рабочей области
        #Window.on_block(self, 1) # вкл блокировку
    # ЛОГИКА
    def on_start(self):
        gorod_index = self.box_gorod.currentIndex()
        db_i = db[gorod_index]        
        self.pole_gorod.setText(str(db_i[0]))
        self.box_1.setCurrentIndex(db_i[1])
        self.box_2.setCurrentIndex(db_i[2])
        self.box_3.setCurrentIndex(db_i[3])
        self.pole_ssv.setText(str(db_i[4]))
        self.box_4.setCurrentIndex(db_i[5])
        self.pole_t_1_2.setText(str(db_i[6]))
        self.pole_t_1_3.setText(str(db_i[7]))
        self.pole_t_2_2.setText(str(db_i[8]))
        self.pole_t_2_3.setText(str(db_i[9]))
        self.pole_sr_1.setText(str(db_i[10]))
        self.pole_sr_2.setText(str(db_i[11]))
        self.pole_sr_12.setText(str(db_i[12]))
        self.pole_sr_13.setText(str(db_i[13]))
        
    
    def on_edit(self):
        Window.on_block(self, 0) # разблокировать
    def on_clear(self):
        self.box_gorod.setCurrentIndex(0)
        self.pole_gorod.clear()
        self.box_1.setCurrentIndex(0)
        self.box_2.setCurrentIndex(0)
        self.box_3.setCurrentIndex(0)
        self.pole_ssv.clear()
        self.box_4.setCurrentIndex(0)
        self.pole_t_1_2.clear()
        self.pole_t_1_3.clear()
        self.pole_t_2_2.clear()
        self.pole_t_2_3.clear()
        self.pole_sr_1.clear()
        self.pole_sr_2.clear()
        self.pole_sr_12.clear()
        self.pole_sr_13.clear()
    def basa_save(self, x=None): # сохранить базу данных
        db_i = [0 for i in list(range(14))]
        # сбор данных
        gorod = self.pole_gorod.text()
        print('gorod = ',gorod)
        db_i[0] = gorod
        db_i[1] = self.box_климат_район.currentIndex()
        db_i[2] = self.box_снег_район.currentIndex()
        db_i[3] = self.box_ветр_район.currentIndex()
        db_i[4] = self.pole_сред_скор_ветра.text()
        db_i[4] = self.in_ch_f(db_i[4])        
        db_i[5] = self.box_гололёд_район.currentIndex()
        db_i[6] = self.pole_t_1_2.text()
        db_i[6] = self.in_ch_f(db_i[6])
        db_i[7] = self.pole_t_1_3.text()
        db_i[7] = self.in_ch_f(db_i[7])
        db_i[8] = self.pole_t_2_2.text()
        db_i[8] = self.in_ch_f(db_i[8])
        db_i[9] = self.pole_t_2_3.text()
        db_i[9] = self.in_ch_f(db_i[9])
        db_i[10] = self.pole_sr_1.text()
        db_i[10] = self.in_ch_f(db_i[10])
        db_i[11] = self.pole_sr_2.text()
        db_i[11] = self.in_ch_f(db_i[11])
        db_i[12] = self.pole_sr_12.text()
        db_i[12] = self.in_ch_f(db_i[12])
        db_i[13] = self.pole_sr_13.text()
        db_i[13] = self.in_ch_f(db_i[13])
        # конец: сбор данных
        # проверка - новый город?
        try: # город есть в базе
            gorod_index = db_goroda.index(gorod)
            db[gorod_index] = db_i
            print('try')
        except:
            print('except')
            db_goroda.append(gorod)
            db_goroda.sort()            
            db.append(db_i)
            db.sort()
            self.box_gorod.addItem(db_i[0])
        # конец: проверка - новый город?
        F_W = open('db_goroda.pkl', 'wb')
        pickle.dump(db,F_W)
        pickle.dump(db_goroda,F_W)
        F_W.close()
        #Window.on_block(self, 1)
    def in_ch_i(self,x):
        try:
            x = int(x)
        except:
            x = 0
        return x
    def in_ch_f(self,x):
        try:
            x = float(x)
        except:
            x = 0
        return x        
    def on_open_isd (self):
        print('db = ',db)
        print('db_goroda = ',db_goroda)
    def on_block (self, block):
        self.pole_gorod.setReadOnly(block) 
        self.pole_ssv.setReadOnly(block)
        self.pole_t_1_2.setReadOnly(block)
        self.pole_t_1_3.setReadOnly(block)
        self.pole_t_2_2.setReadOnly(block)
        self.pole_t_2_3.setReadOnly(block)
        self.pole_sr_1.setReadOnly(block)
        self.pole_sr_2.setReadOnly(block)
        self.pole_sr_12.setReadOnly(block)
        self.pole_sr_13.setReadOnly(block)
    def saveToFile_txt(self): 
        pass
    def saveToFile_html(self): 
        pass
    def on_copy(self):
        pass
# КОНЕЦ
if __name__ == "__main__":
    app = QtGui.QApplication(sys.argv)
    window = Window() # создаёт экземпляр окна из класса
    window.move(40, 20) # сдвиг окна от верхнего левого угла экрана
    window.show() # запускает окно
    sys.exit(app.exec_())
    
PEHDOM
Kyrym
Подскажите, пожалуйста, что у меня не так?

 db[gorod] = db_i
Это что?
смотрим выше
 db = []
епта, да это же список и какой элемент вы хотите получить обратившить к списку как к словарю?
МБ вы хотели вот так сделать?
 db[gorod_index]=db_i
по крайней мере теперь у вас города не дублируются.

ЗЫ почему вы используете два списка? причем в столь извращенной форме?
Не проще использвать один словарь?
Да и вобще хранить все в памяти моветон. Пока у вас 2-3 города для теста все работает, а представте что будет если у вас будет база из десятков тысяч а то и сотен тысяч городов? это ж сколько памяти будет жрать программа чтоб хранить всб базу в памяти?
Kyrym
PEHDOM
db = db_i
Да, с этим я тупанул…
Конечно же, хотел сделать так:
 db[gorod_index]=db_i
Один косяк найден!

PEHDOM
почему вы используете два списка? причем в столь извращенной форме?
Не понимаю, что в этом плохого? Список с городами мне нужен, чтобы вставлять его в раскрывающийся список. С моей точки зрения, делать один большой список, а потом извлекать из него список с городами - вот это как раз будет лишней операцией.

Вряд ли в моей программе будет больше нескольких десятков городов, за память я не беспокоюсь. Но всё-равно, если использовать словарь, то ресурсов используется меньше?
Kyrym
Всё. Сам на свежую голову нашёл последнюю ошибку, в коде поправил, теперь всё работает. Забил вчера голову self'ами )))
PEHDOM
Kyrym
Но всё-равно, если использовать словарь, то ресурсов используется меньше?
При ваших обьемах никакой разницы вы не заметите . ДА и дело не в том, просто у вас вся логика программы основывается на том что данные в двух списках отсортированы одинаков, тоесть в первом списке первый элемент это например, Москва, и во втором он должне быть первым; второй элемент - Питер и во втором списке он доженбыть вторым, и тд… при этом вы достаточно смело делаете постоянно sort(). если вдруг у вас чтото нарушиться или sort не так отсортирует второй список у вас все смешается.

Kyrym
Список с городами мне нужен, чтобы вставлять его в раскрывающийся список. С моей точки зрения, делать один большой список, а потом извлекать из него список с городами - вот это как раз будет лишней операцией.
Не будет. Сравните: извлечь один раз список, или каждый раз когда чтото меняете проделывать манипуляции с двумя списками.
Для лист бокса извлекайте ключи из словаря dict.keys(), сотрируйте и пихайте в листбокс, а потом по этому же ключу получайте содержимое словаря вместо получения индеса из одного списка, а потом измению элмента с таким же индексом в другом списке.
Плюс клнструкции типа вот этого:
 try: # город есть в базе
            gorod_index = db_goroda.index(gorod)
            db[gorod_index] = db_i
            print('try')
        except:
            print('except')
            db_goroda.append(gorod)
            db_goroda.sort()            
            db.append(db_i)
            db.sort()
            self.box_gorod.addItem(db_i[0])
можно будет заменить вот таким:
 dict[cityName]=db_i
Если такого ключа нет, он создаст , если есть заменит существующий.
Kyrym
Хочу спросить. Можно ли блокировать раскрывающийся список, т.е. не нужен метод. аналогичный setReadOnly. В документации к QComboBox() я такого не нашёл.
PEHDOM
И как вы себе это представляете?
можно или убрать все “лишние” варианты, или сделать неактивным: QComboBox.setEnabled(False)
Kyrym
PEHDOM
И как вы себе это представляете?
Я себе представляю это так. При смене городов, я вижу выбранные и сохранённые ранее значения в комбоБоксах, но изменить ничего нельзя, пока не будет включен режим редактирования.

QComboBox.setEnabled(False) - ничего не показывает.
PEHDOM
Kyrym
Я себе представляю это так. При смене городов, я вижу выбранные и сохранённые ранее значения в комбоБоксах, но изменить ничего нельзя, пока не будет включен режим редактирования.
так вы и так не можете ничего изменитьв в комбобоксе, вы можете только выбрать одно из возможных значений. Я чегото не понимаю, что вы хотите редактировать в комбобоксе пока не “включен режим редактирования”?
Kyrym
QComboBox.setEnabled(False) - ничего не показывает.
естествнно, вместо QComboBox нужно указать инстанс вашего комбобокса, хотя судя по написаному выше это не то что вам нужно..
Kyrym
PEHDOM
естествнно, вместо QComboBox нужно указать инстанс вашего комбобокса
Да это понятно, естественно я пробовал типа:
 self.box_1.setEnabled(False)

PEHDOM
Я чегото не понимаю, что вы хотите редактировать в комбобоксе пока не “включен режим редактирования”?
Допустим, программа написана, как я задумал, а так же созданы в базе несколько городов, заполнены поля и комбобоксы - свойства (характеристики) этих городов. Когда я переключаюсь между городами, в поля и боксы подставляются сохранённые значения. По умолчанию, свойства городов менять нельзя, поля и боксы заблочены. Но у меня есть кнопка “Редактировать”. При её нажатии блокировка снимается, а после внесений изменений нажимаем кнопку “сохранить”, и блокировка включается вновь.

Как я уже говорил, мне нужен полный аналог setReadOnly. Но если его нет, то не велика потеря: всё-таки если даже случайно изменить значение комбобокса, то нужно ещё нажать кнопку “сохранить”, только после этого изменения будут сохранены в базе.
___________________________________________________
Добавил функцию удаления выбранного города. С диалогом подтверждения удаления. Правильно ли так писать? Исключение я добавил для случая, когда город не выбран. И ещё вопрос - в QMessageBox можно заменить Yes, No на Да, Нет?
     def on_gorod_del(self):
        reply = QtGui.QMessageBox.question(self, 'Сообщение',
            "Вы действительно хотите удалить город?", QtGui.QMessageBox.Yes, QtGui.QMessageBox.No)
        gorod = self.pole_gorod.text()
        if reply == QtGui.QMessageBox.Yes:
            try:
                gorod_index = db_goroda.index(gorod)
                db_goroda.pop(gorod_index)
                db.pop(gorod_index)
                self.box_gorod.removeItem(gorod_index)
                Window.on_clear(self)
                Window.pkl_save(self)
            except:
                pass
        else:
            pass

P.S.: База данных у меня будет на двух списках, но потом попробую сделать версию со словарём.
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