Как вы читаете отдельные символы из стандартного ввода в Python - PullRequest
0 голосов
/ 08 мая 2018

Есть много хороших ответов о том, как читать с stdin в python, но я просто не могу найти ничего о чтении отдельных символов вместо целых строк. Позвольте мне объяснить:

Мне нужно прочитать информацию, отправленную arduino через последовательный порт, который перенаправляется на стандартный ввод. Эта информация обрабатывается и сохраняется в текстовом файле. Я написал программу на Arduino, чтобы я мог изменить способ отправки информации. План состоял в том, чтобы отправить информацию с начальным (<) и конечным символом (>), чтобы она выглядела следующим образом: <height:2342>

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

Мой скрипт на python будет проверять каждый символ отдельно на наличие начального символа <, в идеале, в том виде, в котором он был введен, и затем собирать информацию до получения >. Я попытался получить ввод, используя inputchar = sys.stdin.read(1). Но проблема здесь в том, что это читается с stdin навсегда, пока не будет захвачен символ новой строки (\n), а затем вернет первый введенный символ.

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

Платформа: Raspberry Pi Zero W, Raspbian Jessy, Python 2.7


Я знаю, что мог бы использовать inputline = sys.stdin.readline() и изменить программу Arduino для отправки новой строки после информации. Затем проанализируйте всю строку (которая может быть очень длинной) и извлеките информацию. Но я не думаю, что это был бы чистый способ сделать это.


Обновление через последовательный порт: К сожалению, я не могу получить доступ к последовательному порту напрямую из python, потому что есть второй скрипт python, который должен записывать в последовательный порт. Поскольку только один может получить доступ к порту, решение состоит в том, чтобы перенаправить последовательный порт на stdin и stdout. См. Мой вопрос Доступ к одному последовательному порту с двумя скриптами Python

Ответы [ 3 ]

0 голосов
/ 08 мая 2018

Я не могу воспроизвести поведение, которое вы описываете ...

Выполнение на моем Распбиане - на RPI2:

$ cat a.py
#!/usr/bin/env python2
import sys

while True:
    print "Got", ord(sys.stdin.read(1))


$ echo -n "Test"  | hexdump -C
00000000  54 65 73 74                                       |Test|
00000004

$ # No newline in the data sent by echo, as shown by hexdump

$ echo -n "Test"  | python2 a.py
Got 84
Got 101
Got 115
Got 116
Got
Traceback (most recent call last):
  File "a.py", line 5, in <module>
    print "Got", ord(sys.stdin.read(1))
TypeError: ord() expected a character, but string of length 0 found

По сути, sys.stdin.read(1) возвращается с любым символом, отправленным со стандартного ввода, без ожидания перевода строки.

0 голосов
/ 08 мая 2018

Это потому, что ваш терминал находится в режиме приготовления . Вы можете использовать, например, tty.setcbreak или curses.cbreak , чтобы отключить буферизацию строки. Это вещь Unix, не особенно специфичная для Python.

Пример:

import sys, tty
tty.setcbreak(sys.stdin.fileno())

Обратите внимание, что это имеет другие эффекты, такие как отключение эха, и будет сохраняться при выходе из вашей программы. Как правило, интерфейс более высокого уровня, такой как контекстный менеджер curses, используется для обработки разбора ключей (например, клавиш со стрелками, отправки управляющих последовательностей) и очистки.

Основным инструментом командной строки вне Python для этого является stty .

0 голосов
/ 08 мая 2018

sys.stdin.read(1) - правильный подход.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...