How to read multiple lines of raw input?
Asked Answered
C

17

89

I want to create a Python program which takes in multiple lines of user input. For example:

This is a multilined input.
It has multiple sentences.
Each sentence is on a newline.

How can I take in multiple lines of raw input?

Confuse answered 26/7, 2012 at 7:29 Comment(5)
If you're taking multiple lines of input, how do you know when the input has ended?Burst
Have a loop that takes raw_input until the user enters 'done' or something.Paule
I guess you're aiming for user input, but you can add newlines \n to the prompt, eg: raw_input('foo\nbar: ')Dauphin
@Confuse Do you only want raw_input solutions or would you be fine with taking the input directly from stdin?Octavus
you could try this link daniweb.com/software-development/python/threads/269208/…Columbuscolumbyne
O
120
sentinel = '' # ends when this string is seen
for line in iter(input, sentinel):
    pass # do things here

To get every line as a string you can do:

'\n'.join(iter(input, sentinel))

Python 2:

'\n'.join(iter(raw_input, sentinel))
Octavus answered 26/7, 2012 at 7:47 Comment(11)
I've been a pythonista for about 6 years now and I never knew of this other form of iter(). You sir are a bl--dy genius!Saiz
How do I set EOF as the sentinel character?Mechanize
@Octavus - does this not allow for a prompt in raw_input? Seems like you cannot pass parameters to the function in the first arg of iter.Move
@Move You can it just won't look as pretty iter(lambda: raw_input('prompt'), sentinel)Octavus
Note that in Python 3, raw_input is now input.Honey
@Honey Added that in now to make answer complete for all pythonsOctavus
When I try printing my input with for x in string_list: print(x), Python prints each individual character on its own line, rather than separating by newlinesEbsen
try for x in string_list.split('\n')Octavus
@StevenVascellaro you can serialize the iterator as a list rather than a string by letting string_list = list(iter(input, sentinel)). Iterating over this will give you the individual linesSchistosome
As a side note, if you want to include a prompt when taking input, you can use: '\n'.join(iter(lambda: raw_input(<put a prompt here>), sentinel)).Provincetown
I posted a question regarding this code to understand it better. Here is the link if anyone needs help.Cascabel
M
21

Alternatively, you can try sys.stdin.read() that returns the whole input until EOF:

import sys
s = sys.stdin.read()
print(s)
Megara answered 1/5, 2017 at 10:21 Comment(1)
This solution is perfect if you want to take in text that has multiple blank lines, or any other data. It stops when it hits EOF (Ctrl+D; Ctrl+Z on Windows).Rhinencephalon
A
8

Keep reading lines until the user enters an empty line (or change stopword to something else)

text = ""
stopword = ""
while True:
    line = raw_input()
    if line.strip() == stopword:
        break
    text += "%s\n" % line
print text
Adrianadriana answered 26/7, 2012 at 7:46 Comment(0)
S
4

Try this

import sys

lines = sys.stdin.read().splitlines()

print(lines)

INPUT:

1

2

3

4

OUTPUT: ['1', '2', '3', '4']

Sandstorm answered 27/9, 2018 at 9:31 Comment(0)
I
3

Just extending this answer https://mcmap.net/q/236259/-how-to-read-multiple-lines-of-raw-input instead of any stop word you can just check whether a line is there or not

content = []
while True:
    line = raw_input()
    if line:
        content.append(line)
    else:
        break

you will get the lines in a list and then join with \n to get in your format.

print '\n'.join(content)
Interlaken answered 18/1, 2018 at 12:59 Comment(0)
S
2

*I struggled with this question myself for such a long time, because I wanted to find a way to read multiple lines of user input without the user having to terminate it with Control D (or a stop word). In the end i found a way in Python3, using the pyperclip module (which you'll have to install using pip install) Following is an example that takes a list of IPs *

import pyperclip

lines = 0

while True:
    lines = lines + 1 #counts iterations of the while loop.

    text = pyperclip.paste()
    linecount = text.count('\n')+1 #counts lines in clipboard content.

    if lines <= linecount: # aslong as the while loop hasn't iterated as many times as there are lines in the clipboard.
        ipaddress = input()
        print(ipaddress)

    else:
        break

For me this does exactly what I was looking for; take multiple lines of input, do the actions that are needed (here a simple print) and then break the loop when the last line was handled. Hope it can be equally helpful to you too.

Situated answered 24/1, 2019 at 23:34 Comment(0)
C
2

With Python 3, you can assign each line to data:

while data := input():
    print("line", data)
Cuxhaven answered 4/2, 2022 at 12:2 Comment(1)
Nifty! Also, to clarify, that loop ends on zero-length input. Might not be obvious to everyone.Skolnik
A
1

sys.stdin.read() can be used to take multiline input from user. For example

>>> import sys
>>> data = sys.stdin.read()
  line one
  line two
  line three
  <<Ctrl+d>>
>>> for line in data.split(sep='\n'):
  print(line)

o/p:line one
    line two
    line three
Algo answered 23/1, 2019 at 16:44 Comment(0)
W
1

The easiest way to read multiple lines from a prompt/console when you know exact number of lines you want your python to read, is list comprehension.

lists = [ input() for i in range(2)]

The code above reads 2 lines. And save inputs in a list.

Waterlog answered 9/3, 2020 at 4:16 Comment(0)
H
0

Its the best way for writing the code in python >3.5 version

a= int(input())
if a:
    list1.append(a)
else:
    break

even if you want to put a limit for the number of values you can go like

while s>0:
a= int(input())
if a:
    list1.append(a)
else:
    break
s=s-1
Helicoid answered 10/8, 2020 at 16:37 Comment(0)
A
0

A more cleaner way (without stop word hack or CTRL+D) is to use Python Prompt Toolkit

We can then do:

from prompt_toolkit import prompt

if __name__ == '__main__':
    answer = prompt('Paste your huge long input: ')
    print('You said: %s' % answer)

It input handling is pretty efficient even with long multiline inputs.

Absorbent answered 5/1, 2021 at 13:1 Comment(0)
S
0

The Python Prompt Toolkit is actually a great answer, but the example above doesn't really show it. A better example is get-multiline-input.py from the examples directory:

#!/usr/bin/env python
from prompt_toolkit import prompt
from prompt_toolkit.formatted_text import HTML


def prompt_continuation(width, line_number, wrap_count):
    """
    The continuation: display line numbers and '->' before soft wraps.
Notice that we can return any kind of formatted text from here.
The prompt continuation doesn't have to be the same width as the prompt
which is displayed before the first line, but in this example we choose to
align them. The `width` input that we receive here represents the width of
the prompt.
    """
    if wrap_count > 0:
        return " " * (width - 3) + "-> "
    else:
        text = ("- %i - " % (line_number + 1)).rjust(width)
        return HTML("<strong>%s</strong>") % text


if __name__ == "__main__":
    print("Press [Meta+Enter] or [Esc] followed by [Enter] to accept input.")
    answer = prompt(
    "Multiline input: ", multiline=True, prompt_continuation=prompt_continuation
)
    print("You said: %s" % answer)

Using this code you get multiline input in which each line can be edited even after subsequent lines are entered. There are some nice additional features, too, such as line numbers. The input is ended by hitting the escape key and then the enter key:

~/Desktop ❯ py prompt.py
Press [Meta+Enter] or [Esc] followed by [Enter] to accept input.
Multiline input: first line of text, then enter
- 2 - second line of text, then enter
- 3 - third line of text, arrow keys work to move around, enter
- 4 - and lines can be edited as desired, until you
- 5 - press the escape key and then the enter key
You said: first line of text, then enter
second line of text, then enter
third line of text, arrow keys work to move around, enter
and lines can be edited as desired, until you
press the escape key and then the enter key
~/Desktop ❯

Schrader answered 7/8, 2021 at 8:29 Comment(0)
S
0

How do you like this? I mimicked telnet. The snippet is highly self-explanatory :)

#!/usr/bin/env python3

my_msg = input('Message? (End Message with <return>.<return>) \n>> ')

each_line = ''
while not each_line == '.':
    each_line = input('>> ')
    my_msg += f'\n{each_line}'

my_msg = my_msg[:-1]  # Remove unwanted period.

print(f'Your Message:\n{my_msg}')
Sinus answered 29/11, 2021 at 3:47 Comment(0)
S
0

Simple, do

lst = [x for x in input("Enter numbers seperated by spaces").split("\n")]
Sheathe answered 21/7, 2022 at 1:17 Comment(0)
A
0
line = input("Please enter lines: ")             
lines = ""             
while line:         
    lines += "\n" + line      
    line = input()  
print(lines) 
Aynat answered 10/11, 2022 at 18:33 Comment(2)
Welcome to Stack Overflow! While this code may solve the question, including an explanation of how and why this solves the problem would really help to improve the quality of your post. Remember that you are answering the question for readers in the future, not just the person asking now. Please edit your answer to add explanations and give an indication of what limitations and assumptions apply.Alyosha
A code-only answer is not high quality. While this code may be useful, you can improve it by saying why it works, how it works, when it should be used, and what its limitations are. Please edit your answer to include explanation and link to relevant documentation.Concurrent
M
0

I developed this function many years ago, and it has been serving its purpose without any issues since then. It is far from being the most elegant, the most efficient, or the fastest, and certainly it does not implement the best practices in python. But it's a simple algorithm that could be more easily translated to other languages, so there are some obvious potencials for improvement and optimizations. I wasn't even going to post it here, but i thought someone could benefit from this as a starting point.

Python 3

def multiline(
        message: str,
        safetyKeyword: list|str,
        show_safetyKeyword: bool = False,
        display_multiline_tag: bool = True,
        show_prompt: bool = True
        ):
    # message : str
    #   Message to be displayed when asking the user for input
    # safetyKeyword : list[str] | str
    #   String (or list of strings) that will break the loop
    # show_safetyKeyword : bool
    #   Determines if the message displayed to the user will contain the list of safety keywords or not
    # display_multiline_tag : bool
    #   Determines whether to display the [ML] tag on every line
    # show_prompt : bool
    #   Flag that controls whether to display the prompt at all.
    #
    # @return str
    # 
    # Usage:
    # >>> text = multiline("Describe how are you felling today.", "--end :)", True)
    # 
    # *** Multiline Interaction - [*nix: Ctrl-D, Windows: Ctrl-Z, to erase previous answer]
    # *** Type one of these words to exit: ['--end :)']
    # *** Describe how are you felling today.
    # [ML] >> Hello
    # [ML] >> This is a test for a multiline input function
    # [ML] >> It has the ability to erase previous linws
    # [ML] >> ^Z
    # [ML] Removed: 'It has the ability to erase previous linws'
    # [ML] >> It has the ability to erase previous lines*. Ops... :)
    # [ML] >> Anyway
    # [ML] >> Cheers
    # [ML] >> --end :)
    #
    # >>> print(text)
    # Hello
    # This is a test for a multiline input function
    # It has the ability to erase previous lines*. Ops... :)
    # Anyway
    # Cheers
    # >>>
    
    # The question needs to be a string to be printed to the user
    if not isinstance(message, str):
        raise TypeError("Message needs to be a string")
    
    # This checks to see if the user provited a list of strings
    # or just a single string. Then a list of strings is created
    # to assure a list of strings (a good candidate for optimization)
    if isinstance(safetyKeyword, list):
        if not all([isinstance(item, str) and len(item) > 0 for item in safetyKeyword]):
            raise TypeError("List of Safety Keywords must contain only non-empty strings")
        safety = [kw.lower() for kw in safetyKeyword]
    elif not isinstance(safetyKeyword, str):
        raise TypeError("Safety Keyword needs to be at least a string")
    else: safety = [safetyKeyword]

    # We are not savages. Have at least one safety keyword
    # otherwise a infinite loop might happen
    if len(safety) < 1:
        raise AssertionError("There must be at least one safety keyword")
    
    # This branch sets up the tag that will be displayed
    # before every line
    if display_multiline_tag: inline_prompt = '[ML] >> '
    else: inline_prompt = ''

    lines = [] # Container for the text
    answer = None # Each line the user inputs

    if show_prompt:
        print("*** Multiline Interaction - [*nix: Ctrl-D, Windows: Ctrl-Z, to erase previous answer]")
        if show_safetyKeyword:
            print("*** Type one of these options to exit:", str(safety)[1:-1])
    print(message)
    # Keep a loop running until the user types a safety keyword
    # In that case, the user wants to finish the text
    # So wraps everything up, and returns the text to the user
    while answer not in safety:
        try:
            # Ask the user's input
            # input() function provides the functionality
            # of throwing exception uppon encountering EOF
            answer = input(inline_prompt)

            # No erase exception thrown so just store the inserted line
            lines.append(answer)
        except EOFError: # User pressed Ctrl-D / Ctrl-Z
            # It'll only try to erase the last line if there is a last line in the first place
            if len(lines) > 0:
                popped = lines.pop()

                # Do something with the removed item, if you want
                # in this case, just print back what was erased
                # and go back asking for input again
                print(inline_prompt, 'Removed:', repr(popped))

    # Returns almost all lines combined with a separation character
    # in this case, a new-line character, could be any character you want :) 
    # The last item in the list will allways be the safety keyword
    return '\n'.join(lines[:-1])
Multiplication answered 12/7, 2023 at 12:24 Comment(0)
K
-2
def sentence_maker(phrase):
    return phrase

results = []
while True:
    user_input = input("What's on your mind: ")
    if user_input == '\end':
        break
    else:
        results.append(sentence_maker(user_input))

print('\n'.join(map(str, results)))
Kilt answered 27/2, 2022 at 9:33 Comment(2)
There are 13 existing answers to this question, including a top-voted, accepted answer with over one hundred votes. Are you certain your solution hasn't already been given? If not, why do you believe your approach improves upon the existing proposals, which have been validated by the community? Offering an explanation is always useful on Stack Overflow, but it's especially important where the question has been resolved to the satisfaction of both the OP and the community. Help readers out by explaining what your answer does different and when it might be preferred.Dereliction
Please read "How to Answer". It helps more if you supply an explanation why this is the preferred solution and explain how it works. We want to educate, not just provide code.Sall

© 2022 - 2024 — McMap. All rights reserved.