LINUX.ORG.RU

[python] помогите поймать ошибку


0

1

Начал учить python, попутно пишу на нем графическую морду к своей проге.

#!/usr/bin/env python3

from gi.repository import Gtk
import os
import subprocess

class Parser():
    def __init__(self):
        self.cpu_info = []
        self.os_info = []
        self.kernel_info = []
        self.users_info = []
    def parse_cpu_info(self):
        pipe = subprocess.Popen(['hardinform', '-c'], 0, None, None,subprocess.PIPE)
        test = lambda x,y: x[:len(y)] == y
        access_count = 0
        cpu_info = self.cpu_info
        cpu_info.append({})
        x = 0
        a = pipe.stdout.readline()
        while a:
            if access_count == 8:
                access_count = 0
                x += 1
                cpu_info.append({})
            if test(a, '\tCPU:'):
                cpu_info[x]['CPU'] = a[len('\tCPU:'):]
                print("CPU number parsed successfully")
                access_count += 1
            elif test(a, '\t\tModel name:'):
                cpu_info[x]['Model name'] = a[len('\t\tModel name:'):]
                access_count += 1
            elif test(a, '\t\tCurrent processor speed in MHz:'):
                cpu_info[x]['Current speed in MHz'] = a[len('\t\tCurrent processor speed in MHz:'):]
                access_count += 1
            elif test(a, '\t\tProcessor cache size:'):
                cpu_info[x]['Cache size'] = a[len('\t\tProcessor cache size:'):]
                access_count += 1
            elif test(a, '\t\tProcessor speed in Bogomips:'):
                cpu_info[x]['Speed in bgmps'] = a[len('\t\tProcessor speed in Bogomips:'):]
                access_count += 1
            elif test(a, '\t\tTemperature:'):
                cpu_info[x]['Temperature'] = a[len('\t\tTemperature:'):]
                access_count += 1
            elif test(a, '\t\tCritical temperature:'):
                cpu_info[x]['Crit temperature'] = a[len('\t\tCritical temperature:'):]
                access_count += 1
            a = pipe.stdout.readline()
    def parse_os_info(self):
        pipe = subprocess.Popen(['hardinform', '-c'])
        test = lambda x,y: x[len(y):] == y
        a = str()
        while a == pipe.communicate()[0]:
            if test.call(a, '\t\tOS version:'):
                pass
            elif test.call(a, '\t\tUptime:'):
                pass
    def parse(self):
        self.parse_cpu_info() 
        #return self.cpu_info
        
class Handler():
    def __init__(self, user_data):
        self.data = user_data
    def add_items_to_categories_tree(self, widget):
        treestore = self.data['categories_tree_store']
        cpu = treestore.append(None, ('CPU',)) 
        os = treestore.append(None, ('OS',))
        users = treestore.append(os, ('Users',))
        kernel = treestore.append(os, ('Kernel',))
    def on_status_icon_activated(self):
        pass
    def on_status_icon_popup_menu(self, status_icon, button, activate_time):
        self.data['status_icon_context_menu'].popup(None, None , self.data['status_icon'].position_menu, self.data['status_icon'], button, activate_time)
    def on_main_window_delete(self, widget, event):
        widget.hide()
    def cpu_item_selected(self):
        pass
    def os_item_selected(self):
        pass
    def kernel_item_selected(self):
        pass
    def users_item_selected(self):
        pass
    def on_categories_tree_row_activated(self, a, v, f):
        text = self.data['categories_tree_curr_text'].props.text
        if text == 'CPU':
            self.cpu_item_selected()
        elif text == 'OS':
            self.os_item_selected()
        elif text == 'Kernel':
            self.kernel_item_selected()
        elif text == 'Users':
            self.users_item_selected()

class Main():
    def __init__(self):
        parser = Parser()
        cpu_data = parser.cpu_info
        print(cpu_data[0]['CPU'])  # вот тут ошибка
        user_data = {}
        gtk_builder = Gtk.Builder()
        gtk_builder.add_from_file("/home/inish777/hardinform/share/hardinform-gui.ui")
        user_data['main_window'] = main_window = gtk_builder.get_object("main_window")
        user_data['categories_tree_curr_text'] = gtk_builder.get_object('curr_categories_tree_text')
        user_data['categories_tree_store'] = gtk_builder.get_object('categories_tree_store')
        user_data['information_tree_store'] = gtk_builder.get_object('information_tree_store')
        user_data['place_for_widgets'] = gtk_builder.get_object('place_for_widgets')
        user_data['status_icon'] = gtk_builder.get_object('hardinform_status_icon')
        user_data['status_icon_context_menu'] = gtk_builder.get_object('status_icon_context_menu')
        user_data['main_hbox'] = gtk_builder.get_object('main_hbox')
        gtk_builder.connect_signals(Handler(user_data))
        main_window.show_all()
        Gtk.main()
Main()
Вот. Пробовал отлаживать в winpdb, он показывает, что парсинг проходит успешно и cpu_info заполняется. Но при попытке обратиться к значению(Main().__init__) происходит исключение IndexError: list index out of range.
cast baverman

★★

parser = Parser()
parser.parse_cpu_info() # а вызвать метод ты забыл?
cpu_data = parser.cpu_info
print(cpu_data[0]['CPU'])  # вот тут ошибка
beka ()
Ответ на: комментарий от beka
[inish777@laptop hardinform]$ ./hardinform-gui.py
Traceback (most recent call last):
  File "./hardinform-gui.py", line 116, in <module>
    Main()
  File "./hardinform-gui.py", line 101, in __init__
    print(cpu_data[0]['CPU'])  # вот тут ошибка
KeyError: 'CPU'
netcat ★★ ()

Начал учить python

Вот здесь и ошибка.

// lovesan

anonymous ()

Толком не вникал, но во-первых, нулевого индекса у cpu_data может и не быть если внутри парсинга на первой итерации случилось access_count == 8 и x инкрементировался. А во-вторых cpu_info[x]['CPU'] тоже пишется только если выполнилось какое-то условие, так-что ключа CPU тоже может и не быть.

В общем, оба ключа надо проверять, тогда ошибка исчезнет, а программа тебе сама скажет что не так (если напишешь естественно).

Kalashnikov ★★★ ()
Ответ на: комментарий от anonymous

Начал учить python

Вот здесь и ошибка.

Если все начнут учить лисп, то с кем же тогда ругаться в Development? :)

DeVliegendeHollander ★★ ()
Ответ на: комментарий от Kalashnikov

А, понял что такое access_count. Костыльно как-то, можно же просто проверять x%8.

А индексы всё равно надо проверять, там ифов много, я например запутался. Собственно эксепшен и говорит что в массиве ты полез за несуществующим индексом.

Kalashnikov ★★★ ()
Ответ на: комментарий от netcat

у тебя какой-то ужас в parse_cpu_info() творится.

Во-первых скажи, что будет если сделать так:

parser = Parser()
parser.parse_cpu_info() 
print parser.cpu_info
exit()

Во-вторых, покажи вывод `hardinform -c`

beka ()
Ответ на: комментарий от beka
[{}]

Вывод `hardinform -c`:

CPU info
        CPU:0
                Processor type:GenuineIntel
                Model name:Intel(R) Core(TM) i5-2410M CPU @ 2.30GHz
                Current processor speed in MHz:800.000
                Processor cache size:3072 KB
                Processor speed in Bogomips:4590.33
                Temperature:0°C
                Critical temperature:127°C
        CPU:1
                Processor type:GenuineIntel
                Model name:Intel(R) Core(TM) i5-2410M CPU @ 2.30GHz
                Current processor speed in MHz:800.000
                Processor cache size:3072 KB
                Processor speed in Bogomips:4588.97
                Temperature:0°C
                Critical temperature:127°C
        CPU:2
                Processor type:GenuineIntel
                Model name:Intel(R) Core(TM) i5-2410M CPU @ 2.30GHz
                Current processor speed in MHz:800.000
                Processor cache size:3072 KB
                Processor speed in Bogomips:4588.99
                Temperature:0°C
                Critical temperature:127°C
        CPU:3
                Processor type:GenuineIntel
                Model name:Intel(R) Core(TM) i5-2410M CPU @ 2.30GHz
                Current processor speed in MHz:2301.000
                Processor cache size:3072 KB
                Processor speed in Bogomips:4588.99
                Temperature:0°C
                Critical temperature:127°C
А в чем конкретно ужас?

netcat ★★ ()
Ответ на: комментарий от DeVliegendeHollander

то с кем же тогда ругаться

С хаскибыдлом.

anonymous ()
Ответ на: комментарий от netcat

ага, смотри:

когда ты делаешь

if test(a, '\tCPU:'):
    ...

то вызывается лямбда:

lambda x,y: x[:len(y)] == y
где у тебя x равен
x == "        CPU:0" 
, а игрек:
у == "\tCPU:"

и так везде

beka ()
Ответ на: комментарий от DeVliegendeHollander

Хаскеллисты не поведутся. В каше с ногтями протеина мало, а они люди спортивные, к штанге привыкшие, им такая диета не по нутру.

Virtuos86 ★★★★★ ()
 if test.call(a, '\t\tOS version:'):

Ты код с Ruby переписывал?

Virtuos86 ★★★★★ ()
Ответ на: комментарий от beka

Этот же гуй, который я написал на С, интерпретирует эту кучу пробелов как '\t' и работает. Или ты не про это?

netcat ★★ ()
Ответ на: комментарий от netcat
>>> y = "\tCPU:"
>>> y[0]
'\t'
>>> x = "    CPU:0" #четыре пробела(!)
>>> x[0]
' ' #пробел
>>> x[1] 
' ' #опять пробел
>>> x[5]
'C'

так понятно?

beka ()
Ответ на: комментарий от netcat

Там вообще лучше регэксп, что-то типа /\s*CPU:\d/, или хотя-бы .strip()

Kalashnikov ★★★ ()
Ответ на: комментарий от beka
№ | y  | x |
-----------
0 | \t |   |
1 | C  |   |
2 | P  |   |
3 | U  |   |
4 | :  |   |
5 |    | C |
6 |    | P |
7 |    | U |
8 |    | : |
9 |    | 0 |
beka ()
Ответ на: комментарий от beka

Построчный ввод

>>> import subprocess
>>> pipe = subprocess.Popen(['hardinform', '-c'], 0, None, None,subprocess.PIPE)
>>> a = pipe.stdout.readline()
>>> a
'CPU info\n' 
>>> a = pipe.stdout.readline()
>>>a
'\tCPU:0\n' 
>>>

netcat ★★ ()

Б-же мой, ну сделай ты вывод в своей проге в виде xml и парси на здоровье. Это же тихий ужас.

geekless ★★ ()

Раз переписывал с Си, мог бы просто main переписать как функцию, вместо того, чтобы помещать в инициализирующий метод левый код. Заменить

class Main():
    def __init__(self):
        parser = Parser()
        cpu_data = parser.cpu_info
        print(cpu_data[0]['CPU'])  # вот тут ошибка
        user_data = {}
        gtk_builder = Gtk.Builder()
        gtk_builder.add_from_file("/home/inish777/hardinform/share/hardinform-gui.ui")
        user_data['main_window'] = main_window = gtk_builder.get_object("main_window")
        user_data['categories_tree_curr_text'] = gtk_builder.get_object('curr_categories_tree_text')
        user_data['categories_tree_store'] = gtk_builder.get_object('categories_tree_store')
        user_data['information_tree_store'] = gtk_builder.get_object('information_tree_store')
        user_data['place_for_widgets'] = gtk_builder.get_object('place_for_widgets')
        user_data['status_icon'] = gtk_builder.get_object('hardinform_status_icon')
        user_data['status_icon_context_menu'] = gtk_builder.get_object('status_icon_context_menu')
        user_data['main_hbox'] = gtk_builder.get_object('main_hbox')
        gtk_builder.connect_signals(Handler(user_data))
        main_window.show_all()
        Gtk.main()
Main()
на
def main():
    parser = Parser()
    cpu_data = parser.cpu_info
    print(cpu_data[0]['CPU'])  # вот тут ошибка
    user_data = {}
    gtk_builder = Gtk.Builder()
    gtk_builder.add_from_file("/home/inish777/hardinform/share/hardinform-gui.ui")

    def fill_user_data(data): user_data[data] = gtk_builder.get_object(data)

    map(fill_user_data, (
        'main_window',
        'categories_tree_curr_text',
        'categories_tree_store',
        'information_tree_store',
        'place_for_widgets',
        'status_icon',
        'status_icon_context_menu',
        'main_hbox',
        )
    )
    gtk_builder.connect_signals(Handler(user_data))
    user_data['main_window'].show_all()
    Gtk.main()

main()

Virtuos86 ★★★★★ ()
Ответ на: комментарий от netcat

Ага. Все так, за исключением одного! Это - Python 2. Ты же его запускаешь как Python 3. Это значит, что у тебя будет:

...
>>>  pipe.stdout.readline()
b'\tCPU:0\n' # обрати внимание на b 
>>>

Тебе нужно конвертировать это в обычную строку.

Значит, вот это:

test = lambda x,y: x[:len(y)] == y

надо заменить на:

test = lambda x,y: x[:len(y)].decode('utf-8') == y

И не забудь о том, что я написал в первом комменте.

А еще лучше будет весь этот код сжечь, и как и сказал geekless — парсить xml.

beka ()

пишу на нем графическую морду к своей проге.

к своей проге.

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

baverman ★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.