Python3 : Using input() how to Read Multiple Lines from pipe (stdin)? - python-3.x

im just curious while learning python3 and didn't found any good explanation on the web, neither here to my question.
reading about input() it says "reads from stdin" so i thought i might experiment and try to use it to read from pipe. and so it does! but only ONE LINE (till EOL). So the next question that came up was
how to read multiple lines from pipe (stdin) using input() ?
i found sys.stdin and used sys.stdin.isatty() to determine if stdin is bound to a tty or not, assuming that if not bound to tty the data is coming from pipe. and so i also found and used successfully sys.stdin.readlines() too to read multiple lines.
but just for my curiosity , is there a way to achieve the same by using the plain input() function ?? so far i didn't found something "to test" if stdin contains more lines without blocking my program.
sorry if all this makes no sense to you.
this is my experimenting code so far without input():
import sys
if sys.stdin.isatty(): # is this a keyboard?
print( "\n\nSorry! i only take input from pipe. "
"not from a keyboard or tty!\n"
"for example:\n$ echo 'hello world' | python3 stdin.py"
""
""
)
else:
print ( "reading from stdin via pipe : \n ")
for line in sys.stdin.readlines():
print(line, end="")
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can these two lines be replaced with
# some construction using plain old input() ?

You can iterate over lines in stdin like any other iterable object:
for line in sys.stdin:
# do something
If you want to read the entire thing into one string, use:
s = sys.stdin.read()
Note that iterating over s would then return one character at a time.
Note that it won't read until there is an EOF terminating stdin.

if you just want to use input() to access lines of the stdin:
print(input()) #prints line 1
print(input()) #prints next line
but lets say you only wanted to access the second line:
input() #accesses the first line
print(input()) #prints second line
Lets say you wanted to take the second line and create an array:
stdin:
10
64630 11735 14216 99233 14470 4978 73429 38120 51135 67060
input()
values = list(map(int, input().split(' ')))
values will equal [64630, 11735, 14216, 99233, 14470, 4978, 73429, 38120, 51135, 67060]

Related

how to compare every line from the middle of the line with every line in a single text file using python?

I am a beginer in python and trying to write a script where it compares the lines a text file and print the unique ones.
Here is the input file. (I want to compare every line after the numeric value after (, ))
Hello world! 'I like scripting', 1: I am learning python.
Hello world! 'I like scripting', 1: I am learning perl.
Hello world! 'I like scripting', 1: I am learning both perl and python.
Hello all! 'I like scripting', 3: I am learning python.
Hello everyone! 'I like scripting', 5: I am learning perl.
Hai! 'I do not like scripting', 2: I am not learning either python or perl.
I am trying to print line1 (because "Hello world! 'I like scripting'" covered three possible cases so I want to print only once) and line 6 (because it is not repeated at all so I would like to print line 6)
It should print (output file should be)
Hello world! I like scripting 1
Hai! I do not like scripting 2
I am in the intial stage in my work
with open ('input.txt') as input, open ('output.txt', 'w') as output:
for line in input:
new_line = line.strip(', ')
I opened the input file and trying to strip every line after (, ) to compare every line.
I got stuck here. Any help would be appreciated.
A simple way is to use dicts and lists.
In this solution I collect all lines in a dictionary whose values are the line starts and the keys the line endinds, and if a line ending is already collected then it's a duplicate, I save it to the duplicates list. Then for each collected key, if it is not in the duplicates list, then I write it to the output file.
#!/usr/bin/env python
collected = dict()
duplicates = list()
with open('input.txt') as infile, open('output.txt', 'w') as output:
for line in infile:
line_start, line_end = line.split(':')
if line_end in collected:
duplicates.append(line_end)
else:
collected[line_end] = line_start.split(', ')[0]
for key in collected:
if key not in duplicates:
output.write(f'{collected[key]}\n')
I guess there are "better" solutions, but couldn't find something yet as readable and clear as this one.

Stuck in infinite loop while trying to read all lines in proc.stdout.readline

I am trying to read each line in proc.stdout.readline and send the lines over the network, for example:
data = b''
for line in iter(proc.stdout.readline, ''):
data += line
clientsocket.send(data)
When I run this code I seem to be stuck in a inifinite loop unable to escape to the line:
clientsocket.send(data)
Is there a more efficient way to read the data? I've tried also with a while loop and breaking 'if not line':
data = b''
while True:
line += proc.stdout.readline()
data += line
if not line:
break
clientsocket.send(data)
This seems to also produce the same results. Is there a more efficient way to read all of the data from proc.stdout.readline?
I've encountered the same very problem. The strange thing that in Python 2.7 it had no problem to converge and actually stop iterating.
During debug (in Python 3.5) I've noticed that all true lines returned with the '\n' character, whereas the line that wasn't suppose to arrive returned as an empty string, i.e. ''. So, I just added an if-clause checking against '' and breaking the loop if positive.
My final version looks as follows:
lines = []
for _line in iter(process.stdout.readline, b''):
if _line == '':
break
lines.append(_line)
One thing that might be worth to mention, is that I used universal_newlines=True argument upon subprocess.Popen(..) call.
The statement: iter(proc.stdout.readline, "") will do a blocking read until it recieves an EOF.
If you want to read all the lines, then you can just do:
data = b''
data = b"".join(proc.stdout.readlines())
There is no other solution than for the proc to produce lines faster.
If you want, you can read lines with timeout (i.e. you can wait to read a select number of characters, or timeout if that number of characters are not read).
Those answers can be found here:
https://stackoverflow.com/a/10759061/6400614 .
https://stackoverflow.com/a/5413588/6400614

Printing output to file with Python

I am trying to create a script that takes a file as input, looks up all the email addresses, and writes them to a designated file.
based on other similar questions, i have ended up with this:
import re
Input = open("inputdata.txt", "r")
regex = re.compile("\b[A-Z0-9._%+-]+#[A-Z0-9.-]+\.[A-Z]{2,4}\b")
Logfile = "Result.txt"
for line in Input:
query = regex.findall(line)
for line in query:
print >>Logfile, query
what am i doing wrong? this outputs nothing.
i am guessing the main problem is "for line in query:", which i have tried changing without any luck.
Cheers!
Edit: i have changed the script as suggested below, with "print (query)" instead.
i still do not get any output.
current script is:
import re
Input = open("Inputdata.txt", "r")
regex = re.compile("\b[A-Z0-9._%+-]+#[A-Z0-9.-]+\.[A-Z]{2,4}\b")
# logfile = "Result.txt"
for line in Input:
query = regex.findall(line)
for line in query:
with open("Result.txt", "a") as logfile:
logfile.write(line)
It outputs nothing, and tells me: " NameError: name "logfile" not defined".
what causes this, and is this the reason there is no output?
Your Logfile variable is just the name of a file, not an actual file object. Also, you should use with to automatically close the file when you are done. Try this:
with open("Result.txt", "a") as logfile:
print >>logfile, "hello world"
print >>logfile, "another line"
But note that in Python 3.x, the syntax is different, as print is no longer a statement but a function:
with open("Result.txt", "a") as logfile:
print("hello world", file=logfile)
print("another line", file=logfile)
Thus, instead of redirecting print, the best choice might be to write to the file directly:
with open("Result.txt", "a") as logfile:
logfile.write("hello world\n")
logfile.write("another line\n")
I don't think, with print you can write to a file without redirecting the output to a file. The way you have used the print, I guess, you want output redirection only.
Let's say your python script is in a file test.py.
replace the line:
print >>Logfile, query
with just:
print query
And from a terminal/cmd, run the script like this:
python test.py >> Result.txt
This is called output redirection.

User input after file input in Python?

First year Comp Sci student here.
I have an assignment that is asking us to make a simple game using Python, which takes an input file to create the game-world (2D grid). You're then supposed to give movement commands via user input afterwards. My program reads the input file one line at a time to create the world using:
def getFile():
try:
line = input()
except EOFError:
line = EOF
return line
...after which it creates a list to represent the line, with each member being a character in the line, and then creates a list containing each of these lists (amounting to a grid with row and column coordinates).
The thing is, I later need to take input in order to move the character, and I can't do this because it still wants to read the file input, and the last line from the file is an EOF character, causing an error. Specifically the "EOF when reading a line" error.
How can I get around this?
Sounds like you are reading the file directly from stdin -- something like:
python3 my_game.py < game_world.txt
Instead, you need to pass the file name as an argument to your program, that way stdin will still be connected to the console:
python3 my_game.py game_world.txt
and then get_file looks more like:
def getFile(file_name):
with open(file_name) as fh:
for line in fh:
return line
File interaction is python3 goes like this:
# the open keyword opens a file in read-only mode by default
f = open("path/to/file.txt")
# read all the lines in the file and return them in a list
lines = f.readlines()
#or iterate them at the same time
for line in f:
#now get each character from each line
for char_in_line in line:
#do something
#close file
f.close()
line terminator for the file is by default \n
If you want something else you pass it as a parameter to the open method (the newline parameter. Default=None='\n'):
open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)

String non callable in python 3

I've met a strange problem while doing the 16th exercice of Learn Python the Hard Way (2nd edition, LPTHW).
I have first typed the code, the copied it, and when I execute the script on my console (with python ex16.py test.txt), the same message appears:
File "ex16.py", line 19, in <module>
line1 = input("line 1: ")
TypeError: 'str' object is not callable
The code is:
from sys import argv
script, filename = argv
print("We're going to erase %r." % filename)
print("If you don't want that, hit CTRL-C (^C).")
print("If you do want that, hit RETURN.")
input = ("?")
print("Opening the file...")
target = open(filename, 'w')
print("Truncating the file. Goodbye!")
target.truncate()
print("Now I'm going to ask you for three lines.")
line1 = input("line 1: ")
line2 = input("line 2: ")
line3 = input("line 3: ")
print("I'm going to write these to the file.")
target.write(line1)
target.write("\n")
target.write(line2)
target.write("\n")
target.write(line3)
target.write("\n")
print("And finally, we close it.")
target.close()
Is this caused by the fact that LPTHW is made for Python 2.7 and I use Python 3.3?
You shadowed the builtin input function right here:
input = ("?")
The equal sign assigns to a variable named input, which shadows the built-in input() function. Remove the equal sign and your code will work:
input("?")
input = ("?")
comment out the above and retry the script.

Resources