LINUX.ORG.RU

Python парсинг строки

 ,


0

3

Есть железка на ком порту. Задача прочитать с нее данные, и распихать по переменным. данные такого вида

18,10,0.00,0.01,500,26.18,32.20,586.39
Пытаюсь делать так:
import serial
ser = serial.Serial( '/dev/ttyUSB1', 9600, timeout=1 )
s = ser.readline()
pm25, pm10, hcho, voc, co2, temp, humidity, summ = s.split(',')
print (pm25)
получаю
python read_air.py 
Traceback (most recent call last):
  File "read_air.py", line 10, in <module>
    pm25, pm10, hcho, voc, co2, temp, humidity, summ = s.split(',')
ValueError: need more than 1 value to unpack

Помогите понять где я дурак

★★★

s.split(',') тебе разобьет это на массив из подстрок и засунет в ОДНУ если не ошибаюсь переменную

пробуй так:

import serial
ser = serial.Serial( '/dev/ttyUSB1', 9600, timeout=1 )
s = ser.readline()
sa = s.split(',')
if len(sa) == 8:
	pm25 = float(sa[0])
	pm10 = float(sa[1])
	hcho = float(sa[2])
	voc = float(sa[3])
	co2 = float(sa[4])
	temp = float(sa[5])
	humidity = float(sa[6])
	summ = float(sa[7])

I-Love-Microsoft ★★★★★
()

По идее должно работать
\> pm25, pm10, hcho, voc, co2, temp, humidity, summ = «18,10,0.00,0.01,500,26.18,32.20,586.39».split(',')
\> print pm10
10

anonymous
()
>>> s="18,10,0.00,0.01,500,26.18,32.20,586.39"
>>> s.split(',')
['18', '10', '0.00', '0.01', '500', '26.18', '32.20', '586.39']
>>> pm25, pm10, hcho, voc, co2, temp, humidity, summ = s.split(',')
>>> 

Так что у тебя из порта читается что-то не то.

tailgunner ★★★★★
()
Ответ на: комментарий от I-Love-Microsoft

Не путай человека, должен был нормально сработать split, если входные данные - строка.

ТС - покажи данные которые пришли.

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

Я и не путаю, просто мой способ проверяет на сколько кусков разбилась строка. Вы ему предлагаете каждый раз принимать строку, не зная содержит ли она необходимые 8 элементов?

s = "18,10,0.00,0.01,500,26.18,32.20,586.39"
sa = s.split(',')
if len(sa) == 8:
    pm25 = float(sa[0])
    pm10 = float(sa[1])
    hcho = float(sa[2])
    voc = float(sa[3])
    co2 = float(sa[4])
    temp = float(sa[5])
    humidity = float(sa[6])
    summ = float(sa[7])

print pm25
print summ
python test.py 
18.0
586.39
I-Love-Microsoft ★★★★★
()

Попробуй первую строчку отбросить, а данные взять только со второй. Правильно же понимаю что железка просто периодически такими строчками плюется?

ei-grad ★★★★★
()
Ответ на: комментарий от I-Love-Microsoft

Написал бы просто «проверь что все 8 элементов отдаются». Нет, обязательно же надо своим незнанием питона народ потроллить...

ei-grad ★★★★★
()
Ответ на: комментарий от I-Love-Microsoft

Ну, проверка это хорошо, но вот эта вот колбаса:

    pm25 = float(sa[0])
    pm10 = float(sa[1])
    hcho = float(sa[2])
    voc = float(sa[3])
    co2 = float(sa[4])
    temp = float(sa[5])
    humidity = float(sa[6])
    summ = float(sa[7])

не нужна. Раз ты проверил что элементов 8, то делаешь

pm25, pm10, hcho, voc, co2, temp, humidity, summ = sa

и не паришся.

gnunixon ★★★
()
Ответ на: комментарий от ei-grad

Я полный нуб в питоне и пишу на нем что-то, относящееся к работе, не более как два месяца. Тем не менее, подход к работе с негарантированными данными не зависит от ЯП. Прежде чем что-то парсить, надо убедиться что там нужное количество элементов, а далее, что там вообще числа.

I-Love-Microsoft ★★★★★
()
Ответ на: комментарий от I-Love-Microsoft

Я не говорю что незнание это плохо, я про то что за портянками кода не видно замечания про проверку входных данных :-). С твоим последним дополнением хватило бы фразы «проверь что все 8 элементов отдаются, и что там вообще числа».

ei-grad ★★★★★
()
>>> s = "18,10,0.00,0.01,500,26.18,32.20,586.39"
>>> pm25, pm10, hcho, voc, co2, temp, humidity, summ = s.split(',')
>>> print(pm25, pm10, hcho, voc, co2, temp, humidity, summ)
18 10 0.00 0.01 500 26.18 32.20 586.39

ЧЯДНТ?

Ты саму эту s напечатай, прежде чем сплитать, небось не те данные пришли.

Ну и раз у тебя данные берутся вот непонятно откуда, лучше вообще проверку сделать, что-то в духе:

try:
    s = serial.readline()
except НеПомнюКакоеИсключениеТам:
    блаблабла, не не получилось вообще
    return что-нибудь  # или s = DEFAULT_S

s = s.split(',')
if len(s) != 8:
    блаблабла, не те данные пришли
    return что-нибудь # ну или exit там, смотря в чём суть
pm25, pm10, hcho, voc, co2, temp, humidity, summ = s

Psych218 ★★★★★
()
Последнее исправление: Psych218 (всего исправлений: 2)
Ответ на: комментарий от I-Love-Microsoft

Щас же набегут разные психи, посмотрят на твой первый коммент и будут копипастить кусок со split и примером ввода с криками ЧЯДНТ :-).

ei-grad ★★★★★
()

По закону подлости свет вырубили. Так что тестить варианты будем позже.

kombrig ★★★
() автор топика
Ответ на: комментарий от Psych218

вот это расово верно! а как проверить что число is_float?

2 ei-grad: исправить уже не могу

I-Love-Microsoft ★★★★★
()
Ответ на: комментарий от ei-grad

Как сделать так, чтобы результат split попадал в переменные не как строки а сразу float? Да чтоб еще если там не float был то не экзепшен а просто 0 записывался?

I-Love-Microsoft ★★★★★
()
Ответ на: комментарий от I-Love-Microsoft

Лолшто?

s.split(',') тебе разобьет это на массив из подстрок и засунет в ОДНУ если не ошибаюсь переменную

Правильно. И именно так и работает множественное присваивание в Питоне. А ты порнографию какую-то предлагаешь вместо.

У ТС затык не в этом.

Virtuos86 ★★★★★
()
Ответ на: комментарий от I-Love-Microsoft

sa = [float(f) if all(i.isdigit() for i in f.split(".", 1)) else 0 for f in s.split(',')]
Но проще float(f) в try/except завернуть, чем проверки выдумывать.
И один момент: после float(f) вместо, например, 22.1 там может оказаться 22.1000000001.

Virtuos86 ★★★★★
()
Последнее исправление: Virtuos86 (всего исправлений: 2)
Ответ на: комментарий от Deleted

плохо ибо нет гарантии что расплитится на 3 части ровно поэтому

если уж совсем игнорировать лишнии манипуляции то

ну и сочетая с ei-grad предложением:


(a, b, c) = map(my_super_func,(s+','*2).split(',')[:3])
qulinxao ★★☆
()
Ответ на: комментарий от qulinxao

если уж совсем игнорировать лишнии манипуляции то

не в том месте костыль, на мой взгляд. Если хочется сунуть голову в песок, то лучше воспользоваться itertools.{repeat,chain}.

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

именно так и работает множественное присваивание в Питоне

нет никакого множественного присваивания, это тупой сахар. Все так и происходит, по всей видимости, сначала возвращается массив, а потом интерпретатор под ковром раскидывает его значения по переменным.(тут вспоминаем мантру «явное лучше неявного»)

А ты порнографию какую-то предлагаешь вместо.

порнография — это как раз экономия на спичках в стиле пистона. Он предложил нормальный вариант.

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

Все так и происходит, по всей видимости

Ключевая фраза, лол.

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

Да, я невнимательно процитал любителя МС.

нет никакого множественного присваивания, это тупой сахар. Все так и происходит, по всей видимости, сначала возвращается массив, а потом интерпретатор под ковром раскидывает его значения по переменным.(тут вспоминаем мантру «явное лучше неявного»)

Я тебя удивлю, но в Питоне и простое присваивание это сахар для:

>>> locals().__setitem__("filequest", None)
>>> filequest
>>> `filequest`
'None'
>>> 

«явное лучше неявного»

При множественном присваивании слева объявляется кортеж из переменных (тип tuple), справа ему присваивается кортеж объектов или примитивных типов. Соответственно кортежи слева и справа синхронно распаковываются и в переменные отправляются ссылки на значения. Тот же механизм по сути используется при вызове функций при использовании оператора «*» для распаковки массивов или кортежей:

>>> def foo(a, b, c): print a, b, c
... 
>>> foo(*[1, 2, 3]) # точно такое множественное присваивание аргументам функции путем распаковки массива
1 2 3
>>> 
Почувствуй суть мощи дизайна Питона: одинаковые приемы и паттерны находят сразу несколько применений в языке и синтаксисе, за счет чего он и ощущается как консистентный, продуманный и логичный.

Virtuos86 ★★★★★
()
Последнее исправление: Virtuos86 (всего исправлений: 2)
Ответ на: комментарий от Virtuos86

суть мощи дизайна Питона

суть мощей пистона, в том, что это пересахаренный, неуклюжий и ущербный в плане ООП псевдодинамический ЯП, к тому же очень неаккуратно спроектированный. Вся суть пистона — оголтелый маркетинг, отсюда и эти финты ушами. подобные дезигнеры хотят почивать на лаврах смоллтока, при этом делать смоллток-лайк мозгов не хватает, вот и получаются эти уродливые суррогаты, благо почва сейчас для этого имеется.

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

а то что ты привел, как раз и есть пример неконсистентности и костыльности, кстати. Это в нормальных языках без сахара делается тривиально, это либо экономия на спичках опять, в лучшем случае, либо, что более вероятно, какие то проблемы с функциями как первоклассными объектами

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

почему так нельзя сделать:

foo := block(a, b, c, writeln(a, b, c))

foo callWithArgList(list(1, 2, 3)) // 123
питон так не может? Обязательно надо через жопу?

Кстати, взгляни краешком глаза на то, что может ООП-язык

foo := block(writeln(a, b, c))

foo clone setScope(Object clone do(a := 1; b := 2; c := 3)) call // 123
потом посанам за бутылкой будешь рассказывать, что ты это видел своими глазами, стало быть жизнь прожита не зря

filequest
()

Попробуй

# …
s = ser.readline()
print(s, s.split(','))
# …

Напечатаешь строку и список, в который считанная строка разбивается.

Должен увидеть, в какой момент считывается что-то не то. Либо чисел не то количество, либо вообще не то, что надо в принципе. В любом случае, дальше уже надо будет отдельно думать.

evilface ★★
()
Ответ на: комментарий от filequest
foo := block(a, b, c, writeln(a, b, c))

foo callWithArgList(list(1, 2, 3)) // 123
>>> def foo(a, b, c):
...     print(a, b, c)
... 
>>> foo(1, 2, 3)
1 2 3
>>> 
foo := block(writeln(a, b, c))

foo clone setScope(Object clone do(a := 1; b := 2; c := 3)) call // 123
>>> def foo():
...     print(a, b, c)
... 
>>> def call_with_scope(f, **scope):
...     globals().update(scope)
...     return f()
... 
>>> call_with_scope(foo, a=1, b=2, c=3)
1 2 3
>>>
anonymous
()
Ответ на: комментарий от anonymous

Не, даже не так:

class Scope:
    def __init__(self, **scope):
        self.scope = scope
    def __enter__(self):
        self.gc = globals().copy()
        globals().update(self.scope)
    def __exit__(self, t, v, tb):
        globals().clear()
        globals().update(self.gc)

def foo():
    print(a, b, c)

a = 'old a'

with Scope(a=1, b=2, c=3):
    foo() # 1 2 3

print(a) # old a

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

Если этот пример:

foo := block(a, b, c, writeln(a, b, c))

foo callWithArgList(list(1, 2, 3)) // 123
аналог питоньего:
>>> def foo(a, b, c): print a, b, c
... 
>>> foo(*[1, 2, 3])
то у тебя свое особое чувство прекрасного. На мой взгляд, жопа это «callWithArgList», хотя стоит признать, что жопа эта вполне говорящая. Если заменить «*» на «callWithArgList», примеры будут идентичны. Так почему Io-вариант ты считаешь чем-то лучше?

потом посанам за бутылкой будешь рассказывать

Пожалуйста, не проецируй на окружающих свои будни.

Извини, второй пример я не осилил. Видимо, там ненужный и необоснованный ничем, кроме понтов, пердолинг с воспетым тобой метапогромированием в Io.

Virtuos86 ★★★★★
()
Последнее исправление: Virtuos86 (всего исправлений: 1)
Ответ на: комментарий от anonymous

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

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

Ты в обоих случаях не то написал.

А что нужно?

Ты просто вызвал функцию с аргументами, да маленький?

Да. А ты что сделал? И зачем это нужно?

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

примеры будут идентичны. Так почему Io-вариант ты считаешь чем-то лучше?

Нет не будут идентичны. callWithArgList — это обычное сообщение, а у тебя уродливый синтаксис, подковерное передрачивание.

второй пример я не осилил

создаем экземпляр функции foo, сеттим ему лексический скоп(окружение), вызываем.

filequest
()
Ответ на: комментарий от Deleted

Этот субъект из немаргинальных ЯП знает только JS. Зачем я ему скармливать «iterable», про который придется портянку писать, чтобы объяснить что это и с чем его едят?

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

В первом случае применить к функции список из аргументов, те, foo callWithArgList(someList) — это не то же самое, что вызвать с аргуметами, по второму выше написал, это вряд ли у тебя выйдет, сомневаюсь что в пистоне функциии — Ъ объекты, от которых можно наследовать

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

Не верный. В моем случае, вызывается не сама функция, а ее экземпляр. К тому же, в моем случае, setScope — сообщение, а в его требуется отдельная обертка. К тому же with, это тоже скорей всего синтаксис. Совершенно не то.

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

В первом случае применить к функции список из аргументов, те, foo callWithArgList(someList) — это не то же самое, что вызвать с аргуметами, по второму выше написал, это вряд ли у тебя выйдет, сомневаюсь что в пистоне функциии — Ъ объекты, от которых можно наследовать

>>> def foo(a, b, c):
...     print(a, b, c)
... 
>>> foo.__call__(1, 2, 3)
1 2 3
>>> foo.__call__.__call__(4, 5, 6)
4 5 6
>>> 
anonymous
()
Ответ на: комментарий от filequest

создаем экземпляр функции foo, сеттим ему лексический скоп(окружение), вызываем.

Сомневаюсь, что в питоне это возможно.
Сомневаюсь, что в этой фиче есть практический смысл.

Кстати, зачем создавать несколько экземпляров функции, если функция — это блок кода? Зачем несколько идентичных блоков кода?

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