Как вы читаете со стандартного ввода? - PullRequest
1317 голосов
/ 20 сентября 2009

Я пытаюсь выполнить некоторые задачи code golf , но все они требуют ввода данных из stdin. Как мне получить это в Python?

Ответы [ 21 ]

13 голосов
/ 27 сентября 2018

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 на здесь string :

./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 -
7 голосов
/ 21 июля 2014

Вы можете прочитать из стандартного ввода и затем сохранить входные данные в «данные» следующим образом:

data = ""
for line in sys.stdin:
    data += line
7 голосов
/ 27 августа 2013

Попробуйте это:

import sys

print sys.stdin.read().upper()

и проверьте его с помощью:

$ echo "Hello World" | python myFile.py
6 голосов
/ 07 ноября 2016

Я очень удивлен, что никто не упомянул этот хак до сих пор:

python -c "import sys;print (''.join([l for l in sys.stdin.readlines()]))"

совместим с python2 и python3

5 голосов
/ 14 августа 2016

Чтение из 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()
4 голосов
/ 02 ноября 2017

У меня проблема с решением

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)
2 голосов
/ 29 октября 2014

У меня были некоторые проблемы, когда он работал для чтения через сокеты, переданные по нему. Когда сокет закрылся, он начал возвращать пустую строку в активном цикле. Так что это мое решение (которое я тестировал только в 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

1 голос
/ 09 июня 2016

Относительно этого:

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
0 голосов
/ 30 июня 2019

При использовании команды -c в качестве хитрого способа вместо чтения stdin (и в некоторых случаях более гибкого) вы можете также передать команду сценария оболочки в команду python, поместив команду sell в кавычки в скобках, начинающихся со знака $.

, например

python3 -c "import sys; print(len(sys.argv[1].split('\n')))" "$(cat ~/.goldendict/history)"

Будет подсчитано количество строк из файла истории goldendict.

0 голосов
/ 04 мая 2019

Для 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...