2016-11-14 2 views
31

Насколько велика мощность, которую я могу подавать на функцию input()?Насколько велика может быть вход для функции ввода()?

К сожалению, не было простого способа проверить его. После использования большого количества копий я не смог получить input, чтобы сбой на любом вводе, который я поставил. (И я в конце концов отказался)

documentation для функции input ничего не говорится об этом:

Если prompt аргумент присутствует, он записывается в стандартный вывод без завершающего символа новой строки. Затем функция считывает строку из ввода, преобразует ее в строку (зачищая конечную новую строку) и возвращает ее. Когда считывается EOF, поднимается EOFError.

Итак, я предполагаю, что нет предела? Кто-нибудь знает, есть ли, и если да, то сколько это?

+0

Связанный: http://stackoverflow.com/q/1739913/5647260 – Li357

+1

«* после многократного копирования *« вы пробовали [перенаправление stdin] (http://stackoverflow.com/a/15680903/1013719)? –

+0

У меня не было @RyanHaining спасибо за это! – user6774416

ответ

29

Конечно, нет, он не может быть безграничным *. Ключевая фраза из документации, что я считаю потребности на первый план является:

[...] В этом случае функции считывает строку из ввода, преобразует его в строку (отпарной завершающий символ новой строки) [... ]

(курсив мой)

Поскольку он преобразует входные вы поставку в Pythonstr объекта, по существу переводит к: «ее размер имеет, чтобы быть меньше или равным самой большой строке, которую может создать Python ».

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

* В CPython, по крайней мере, наибольший размер строки ограничена, насколько велика его индекс позволено быть (см PEP 353). То есть, насколько велика цифра в скобках [] разрешено быть, когда вы пытаетесь индексироваться:

>>> s = '' 
>>> s[2 ** 63] 

IndexErrorTraceback (most recent call last) 
<ipython-input-10-75e9ac36da20> in <module>() 
----> 1 s[2 ** 63] 

IndexError: cannot fit 'int' into an index-sized integer 

(попробуйте предыдущий с 2 ** 63 - 1, что это положительный приемлемый предел, -2 ** 63 является отрицательным предел.)

Для индексов это не номера Python, которые используются внутри; вместо этого это Py_ssize_t, который является подписанным 32/64 бит int на 32/64 бит машинах соответственно. Итак, это жесткий предел того, что кажется.

(как говорится, сообщение об ошибке, Int и Intex размера целое число две разные вещи)

Кроме того, представляется, как input() explicitly checks, если вход поступает больше, чем PY_SSIZE_T_MAX (максимальный размер Py_ssize_t) перед преобразованием:

if (len > PY_SSIZE_T_MAX) { 
    PyErr_SetString(PyExc_OverflowError, 
        "input: input too long"); 
    result = NULL; 
} 

Затем он преобразует входные данные в Python str с PyUnicode_Decode.


Чтобы представить это в перспективе для вас; если средняя книга длиной 500.000 символов и estimation за общее количество книг составляет около 130 миллионов вы могли бы теоретически input вокруг:

>>> ((2 ** 63) - 1) // 500000 * 130000000 
141898 

раз эти символы; вероятно, вам понадобится некоторое время :-) (и вы будете ограничены доступной памятью в первую очередь!)

+5

[Сколько времени стоит \ [кусок \] строки?] (Https://en.wiktionary.org/wiki/how_long_is_a_piece_of_string) – wim

+0

Я пробовал это в интерактивном сеансе (linux xterm) и получал очень странные реакции (после вставки около 30 тыс. символов, используя среднюю кнопку мыши), выглядит как очень медленная печать строки (1 строка в секунду). Вероятно, проблема Python здесь, но замедление в readline/xterm или у вас есть другая идея, что вызывает это? – mkiever

+0

Я согласен с вами, не имеет смысла, чтобы это было ошибкой Pythons. Я действительно сомневаюсь в интерактивных сессиях, где построено плавное управление дампом на 30 тыс. Символов, но опять же я не смотрел на эти @mkiever –

13

Мы можем найти ответ на экспериментально довольно легко. Сделайте два файла:

make_lines.py:

num_lines = 34 

if __name__ == '__main__': 
    for i in range(num_lines): 
     print('a' * (2 ** i)) 

read_input.py:

from make_lines import num_lines 

for i in range(num_lines): 
    print(len(input())) 

Затем запустите эту команду в Linux или OSX (я не знаю эквивалент для Windows):

python make_lines.py | python3 read_input.py 

На моем компьютере ему удается закончить, но борьба к концу, замедление o эти процессы значительно. Последнее, что он печатает, - 8589934592, т. Е. 8 GiB. Вы можете узнать ценность для себя в соответствии с вашим определением того, что приемлемо с точки зрения времени и объема памяти.