Я пытаюсь выполнить некоторые задачи по коду в гольф , но все они требуют ввода информации stdin
. Как мне получить это в Python?
Я пытаюсь выполнить некоторые задачи по коду в гольф , но все они требуют ввода информации stdin
. Как мне получить это в Python?
Ответы:
Вы можете использовать fileinput
модуль:
import fileinput
for line in fileinput.input():
pass
fileinput
будет проходить по всем строкам ввода, указанным в качестве имен файлов, указанных в аргументах командной строки, или стандартного ввода, если аргументы не предоставлены.
Примечание: line
будет содержать завершающий перевод строки; чтобы удалить это использоватьline.rstrip()
Есть несколько способов сделать это.
sys.stdin
это файл-подобный объект, для которого вы можете вызывать функции, read
или readlines
если вы хотите прочитать все или вы хотите прочитать все и автоматически разделить его на новую строку. (Вам нужно, чтобы import sys
это работало.)
Если вы хотите запросить ввод данных у пользователя, вы можете использовать его raw_input
в Python 2.X и только input
в Python 3.
Если вы на самом деле просто хотите прочитать параметры командной строки, вы можете получить к ним доступ через список sys.argv .
Вы, вероятно, найдете эту статью Wikibook о вводе / выводе в Python также полезной ссылкой.
import sys
for line in sys.stdin:
print(line)
Обратите внимание, что это будет включать символ новой строки в конце. Чтобы удалить line.rstrip()
перевод строки в конце, используйте, как сказал @brittohalloran.
\r\n
окончаниями строк
Python также имеет встроенные функции input()
и raw_input()
. Смотрите документацию по Python в разделе Встроенные функции .
Например,
name = raw_input("Enter your name: ") # Python 2.x
или
name = input("Enter your name: ") # Python 3
Вот из изучения Python :
import sys
data = sys.stdin.readlines()
print "Counted", len(data), "lines."
В Unix вы можете проверить это, выполнив что-то вроде:
% cat countlines.py | python countlines.py
Counted 3 lines.
В Windows или DOS вы должны сделать:
C:\> type countlines.py | python countlines.py
Counted 3 lines.
cat
здесь является излишним. Правильный вызов для систем Unix является python countlines.py < countlines.py
.
readlines()
. Файловые объекты предназначены для итерации без материализации всех данных в памяти.
Как вы читаете со стандартного ввода в Python?
Я пытаюсь выполнить некоторые задачи кода, но все они требуют ввода от stdin. Как мне получить это в Python?
Ты можешь использовать:
sys.stdin
- Файловый объект - вызов, sys.stdin.read()
чтобы прочитать все.input(prompt)
- передать ему необязательный запрос на вывод, он читает от стандартного ввода до первой новой строки, которую он удаляет. Вам придется делать это несколько раз, чтобы получить больше строк, в конце ввода это вызывает EOFError. (Вероятно, не подходит для игры в гольф.) В Python 2 это так rawinput(prompt)
.open(0).read()
- В Python 3 встроенная функция open
принимает файловые дескрипторы (целые числа, представляющие ресурсы ввода-вывода операционной системы), а 0 - дескриптор stdin
. Он возвращает похожий на файл объект sys.stdin
- вероятно, ваш лучший выбор для игры в гольф. В Python 2 это так io.open
.open('/dev/stdin').read()
- похоже open(0)
, работает на Python 2 и 3, но не на Windows (или даже Cygwin).fileinput.input()
- возвращает итератор над строками во всех файлах, перечисленных в sys.argv[1:]
, или стандартный ввод, если не указан. Используйте как ''.join(fileinput.input())
.И то sys
и другое fileinput
должно быть импортировано, соответственно, конечно.
sys.stdin
примеры, совместимые с Python 2 и 3, Windows, UnixВам просто нужно read
из sys.stdin
, например, если вы данные по конвейеру стандартного ввода:
$ echo foo | python -c "import sys; print(sys.stdin.read())"
foo
Мы видим, что sys.stdin
в текстовом режиме по умолчанию:
>>> import sys
>>> sys.stdin
<_io.TextIOWrapper name='<stdin>' mode='r' encoding='UTF-8'>
Скажем, у вас есть файл, inputs.txt
мы можем принять этот файл и записать его обратно:
python -c "import sys; sys.stdout.write(sys.stdin.read())" < inputs.txt
Вот полная, легко воспроизводимая демонстрационная программа с использованием двух методов: встроенной функции input
(используется raw_input
в Python 2) и sys.stdin
. Данные не изменены, поэтому обработка не является операцией.
Для начала давайте создадим файл для входных данных:
$ python -c "print('foo\nbar\nbaz')" > inputs.txt
И используя код, который мы уже видели, мы можем проверить, что мы создали файл:
$ python -c "import sys; sys.stdout.write(sys.stdin.read())" < inputs.txt
foo
bar
baz
Вот справка по sys.stdin.read
Python 3:
read(size=-1, /) method of _io.TextIOWrapper instance
Read at most n characters from stream.
Read from underlying buffer until we have n characters or we hit EOF.
If n is negative or omitted, read until EOF.
input
( raw_input
в Python 2)Встроенная функция input
читает от стандартного ввода до новой строки, которая удаляется (дополняет print
, по умолчанию добавляет новую строку.) Это происходит до тех пор, пока не получит EOF (конец файла), после чего она поднимается EOFError
.
Таким образом, вот как вы можете использовать input
в Python 3 (или raw_input
в Python 2) чтение из stdin - поэтому мы создаем модуль Python, который мы называем stdindemo.py:
$ python -c "print('try:\n while True:\n print(input())\nexcept EOFError:\n pass')" > stdindemo.py
И давайте распечатать его обратно, чтобы убедиться, что это так, как мы ожидаем:
$ python -c "import sys; sys.stdout.write(sys.stdin.read())" < stdindemo.py
try:
while True:
print(input())
except EOFError:
pass
Опять же, input
читает до новой строки и по существу удаляет его из строки. print
добавляет новую строку. Поэтому, пока они оба изменяют ввод, их модификации отменяются. (Таким образом, они по существу являются дополнением друг друга.)
И когда input
получает символ конца файла, он вызывает EOFError, который мы игнорируем и затем выходим из программы.
А в Linux / Unix мы можем передать из cat:
$ cat inputs.txt | python -m stdindemo
foo
bar
baz
Или мы можем просто перенаправить файл из stdin:
$ python -m stdindemo < inputs.txt
foo
bar
baz
Мы также можем выполнить модуль как скрипт:
$ python stdindemo.py < inputs.txt
foo
bar
baz
Вот справка по встроенному input
из Python 3:
input(prompt=None, /)
Read a string from standard input. The trailing newline is stripped.
The prompt string, if given, is printed to standard output without a
trailing newline before reading input.
If the user hits EOF (*nix: Ctrl-D, Windows: Ctrl-Z+Return), raise EOFError.
On *nix systems, readline is used if available.
sys.stdin
Здесь мы делаем демонстрационный скрипт, используя sys.stdin
. Эффективный способ перебора файловоподобного объекта - использование файловоподобного объекта в качестве итератора. Дополнительный метод для записи в стандартный вывод из этого ввода - просто использовать sys.stdout.write
:
$ python -c "print('import sys\nfor line in sys.stdin:\n sys.stdout.write(line)')" > stdindemo2.py
Распечатайте его обратно, чтобы убедиться, что он выглядит правильно:
$ python -c "import sys; sys.stdout.write(sys.stdin.read())" < stdindemo2.py
import sys
for line in sys.stdin:
sys.stdout.write(line)
И перенаправить ввод в файл:
$ python -m stdindemo2 < inputs.txt
foo
bar
baz
Гольф в команду:
$ python -c "import sys; sys.stdout.write(sys.stdin.read())" < inputs.txt
foo
bar
baz
Поскольку файловые дескрипторы для stdin
и stdout
равны 0 и 1 соответственно, мы также можем передать их open
в Python 3 (не 2, и обратите внимание, что нам все еще нужна буква 'w' для записи в стандартный вывод).
Если это работает в вашей системе, это сбрит больше символов.
$ python -c "open(1,'w').write(open(0).read())" < inputs.txt
baz
bar
foo
Python 2 также io.open
делает это, но импорт занимает гораздо больше места:
$ python -c "from io import open; open(1,'w').write(open(0).read())" < inputs.txt
foo
bar
baz
Один комментарий предлагает ''.join(sys.stdin)
для игры в гольф, но на самом деле это дольше, чем sys.stdin.read () - плюс Python должен создать дополнительный список в памяти (вот как str.join
работает, когда не дан список) - для контраста:
''.join(sys.stdin)
sys.stdin.read()
Верхний ответ предполагает:
import fileinput
for line in fileinput.input():
pass
Но, поскольку sys.stdin
реализует файловый API, включая протокол итератора, это то же самое, что и это:
import sys
for line in sys.stdin:
pass
Другой ответ действительно предлагает это. Просто помните, что если вы делаете это в интерпретаторе, вам нужно Ctrl- dесли вы работаете в Linux или Mac или Ctrl- zв Windows (после Enter), чтобы отправить символ конца файла процессу. Кроме того, этот ответ предлагает print(line)
- который добавляет '\n'
в конце - использовать print(line, end='')
вместо этого (если в Python 2 вам понадобится from __future__ import print_function
).
Реальный вариант использования fileinput
- для чтения в серии файлов.
Ответ, предложенный другими:
for line in sys.stdin:
print line
очень прост и питоничен, но следует отметить, что сценарий будет ждать до EOF, прежде чем начать итерацию по строкам ввода.
Это означает, что tail -f error_log | myscript.py
не будет обрабатывать строки, как ожидалось.
Правильный сценарий для такого варианта использования будет:
while 1:
try:
line = sys.stdin.readline()
except KeyboardInterrupt:
break
if not line:
break
print line
ОБНОВЛЕНИЕ
Из комментариев было убрано, что только на python 2 может быть задействована буферизация, так что вы в конечном итоге ожидаете заполнения буфера или EOF перед вызовом печати.
for line in sys.stdin:
Картина не ждать EOF. Но если вы тестируете очень маленькие файлы, ответы могут быть помещены в буфер. Протестируйте с большим количеством данных, чтобы увидеть, что он читает промежуточные результаты.
print line
не проснулся в 3.1.3, но print(line)
делает.
for line in sys.stdin:
не "блокировать до EOF". В Python 2 есть ошибка опережающего чтения, которая задерживает строки до тех пор, пока соответствующий буфер не будет заполнен. Это проблема буферизации, не связанная с EOF. Чтобы обойти это, используйте for line in iter(sys.stdin.readline, ''):
(используйте io.open()
для обычных файлов). Вам не нужно это в Python 3.
Основываясь на использовании всех ответов sys.stdin
, вы также можете сделать что-то вроде следующего, чтобы прочитать из файла аргументов, если существует хотя бы один аргумент, и в противном случае вернуться к stdin:
import sys
f = open(sys.argv[1]) if len(sys.argv) > 1 else sys.stdin
for line in f:
# Do your stuff
и использовать его как либо
$ python do-my-stuff.py infile.txt
или
$ cat infile.txt | python do-my-stuff.py
или даже
$ python do-my-stuff.py < infile.txt
Это заставит ваш скрипт на Python вести себя как многие программы GNU / Unix, такие как cat
, grep
и sed
.
argparse
это простое решениеПример совместим с обеими версиями Python 2 и 3:
#!/usr/bin/python
import argparse
import sys
parser = argparse.ArgumentParser()
parser.add_argument('infile',
default=sys.stdin,
type=argparse.FileType('r'),
nargs='?')
args = parser.parse_args()
data = args.infile.read()
Вы можете запустить этот скрипт разными способами:
1. Использование stdin
echo 'foo bar' | ./above-script.py
или короче, заменив echo
на здесь строки :
./above-script.py <<< 'foo bar'
2. Использование аргумента имени файла
echo 'foo bar' > my-file.data
./above-script.py my-file.data
3. Использование stdin
через специальное имя файла-
echo 'foo bar' | ./above-script.py -
add_argument('--in'
а затем направить к сценарию и добавить --in -
в командную строку. PS in
не очень хорошее имя для переменной / атрибута.
in
не просто плохое имя для переменной, это недопустимо. args.in.read()
вызовет ошибку InvalidSyntax из-за in
зарезервированного ключевого слова. Можно просто переименовать так, infile
как это делают документы на python argparse: docs.python.org/3/library/…
Вам поможет следующий фрагмент кода (он будет считывать все блокирующие stdin EOF
в одну строку):
import sys
input_str = sys.stdin.read()
print input_str.split()
Я очень удивлен, что никто не упомянул этот хак до сих пор:
python -c "import sys; set(map(sys.stdout.write,sys.stdin))"
в python2 вы можете отбросить set()
вызов, но это будет слово в любом случае
readlines
это разделение на строки, а затем join
снова? Вы можете просто написатьprint(sys.stdin.read())
write
возвращается None
, и размер набора никогда не будет больше 1 ( =len(set([None]))
)
Вы можете читать из stdin и затем сохранять входные данные в «data» следующим образом:
data = ""
for line in sys.stdin:
data += line
data = sys.stdin.read()
без проблем повторных конкатенаций строк.
Читайте sys.stdin
, но чтобы читать двоичные данные в Windows , вам нужно быть очень осторожным, потому sys.stdin
что они открыты в текстовом режиме и будут повреждены, \r\n
заменив их\n
.
Решение состоит в том, чтобы установить режим в двоичный режим, если обнаружен Windows + Python 2, и использовать Python 3 sys.stdin.buffer
.
import sys
PY3K = sys.version_info >= (3, 0)
if PY3K:
source = sys.stdin.buffer
else:
# Python 2 on Windows opens sys.stdin in text mode, and
# binary data that read from it becomes corrupted on \r\n
if sys.platform == "win32":
# set sys.stdin to binary mode
import os, msvcrt
msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY)
source = sys.stdin
b = source.read()
Я использую следующий метод, он возвращает строку из стандартного ввода (я использую его для анализа JSON). Он работает с pipe и подсказкой в Windows (пока не тестировался в Linux). При запросе два разрыва строки указывают на конец ввода.
def get_from_stdin():
lb = 0
stdin = ''
for line in sys.stdin:
if line == "\n":
lb += 1
if lb == 2:
break
else:
lb = 0
stdin += line
return stdin
Проблема у меня с решением
import sys
for line in sys.stdin:
print(line)
в том, что если вы не передадите данные в stdin, он будет заблокирован навсегда. Вот почему мне нравится этот ответ : сначала проверьте, есть ли какие-то данные на stdin, а затем прочитайте их. Это то, что я в итоге сделал:
import sys
import select
# select(files to read from, files to write to, magic, timeout)
# timeout=0.0 is essential b/c we want to know the asnwer right away
if select.select([sys.stdin], [], [], 0.0)[0]:
help_file_fragment = sys.stdin.read()
else:
print("No data passed to stdin", file=sys.stderr)
sys.exit(2)
select
вызове ввод почти никогда не будет «готов» ; или вы также можете столкнуться с проблемами, если stdin подключен к файлу на медленном носителе (сеть, компакт-диск, лента и т. д.). Вы сказали, что «если вы не передадите данные в stdin, они будут заблокированы навсегда». это проблема , но я бы сказал, что это особенность . Большинство программ CLI (например cat
) работают таким образом, и они ожидаются. EOF - единственная вещь, от которой вы должны зависеть, чтобы определить конец ввода.
У меня были некоторые проблемы при получении этого для работы через сокеты, переданные по каналу. Когда сокет закрылся, он начал возвращать пустую строку в активном цикле. Так что это мое решение (которое я тестировал только в Linux, но надеюсь, что оно работает во всех других системах)
import sys, os
sep=os.linesep
while sep == os.linesep:
data = sys.stdin.readline()
sep = data[-len(os.linesep):]
print '> "%s"' % data.strip()
Поэтому, если вы начнете прослушивать сокет, он будет работать правильно (например, в bash):
while :; do nc -l 12345 | python test.py ; done
И вы можете позвонить с помощью telnet или просто указать браузер на localhost: 12345
В соответствии с этим:
for line in sys.stdin:
Я только что попробовал это на python 2.7 (следуя чьему-либо предложению) для очень большого файла, и я не рекомендую его именно по причинам, указанным выше (в течение долгого времени ничего не происходит).
Я получил немного более питонное решение (и оно работает с большими файлами):
with open(sys.argv[1], 'r') as f:
for line in f:
Затем я могу запустить скрипт локально как:
python myscript.py "0 1 2 3 4..." # can be a multi-line string or filename - any std.in input will work
sys.stdin
качестве аргумента командной строки сценарий.
sys.stdin
в качестве аргумента командной строки сценарий? Аргументы - это строки, а потоки - это файловые объекты, они не одинаковы.
sys.stdin
это
Для Python 3 это будет:
# Filename e.g. cat.py
import sys
for line in sys.stdin:
print(line, end="")
Это в основном простая форма cat (1), так как она не добавляет символ новой строки после каждой строки. Вы можете использовать это (после того, как Вы отметили исполняемый файл, используя chmod +x cat.py
такие как:
echo Hello | ./cat.py
При использовании -c
команды, как хитрый способ, вместо чтения stdin
(и в некоторых случаях более гибкого) вы можете передать команду сценария оболочки также вашей команде python, поместив команду sell в кавычки в скобках, начинающихся с$
знака.
например
python3 -c "import sys; print(len(sys.argv[1].split('\n')))" "$(cat ~/.goldendict/history)"
Это будет считать количество строк из файла истории Goldendict.