Python Script Issue (List displaying in one long string vice a new line "\n") - python-3.x

Python Script Output IMAGE
I am writing a script which takes the /etc/shadow and outputs it to a list on the screen to present to viewers. However, the output comes out as one long list vice a list that outputs to each newline. Even if I try to insert a new line character. I figured it out before but changed it to a dictionary and then went back when that was not working. I just want it to print after each shadow file line:
Code:
with open('/etc/shadow', 'r') as file:
lines = [line.rstrip() for line in file]
print(lines)
Output: (Image which cannot be attached...)
Output expected is a new line between each element in the list. However, it only outputs as a single , between each list. I know its the way I did the for loop or a least that is what I am guessing. However, I cannot figure it out. (New to scripting). Thank you.

lines is a list of lines from the file. When you print(lines), you're printing a list.
>>> print(["a", "b", "c" ])
['a', 'b', 'c']
You can print each line in a for loop:
>>> for line in [ "a", "b", "c" ]:
... print(line.rstrip())
...
a
b
c
or you can join with \n all the lines together into a string:
>>> print("\n".join(["a","b","c"]))
a
b
c
Joining lines into a string will need to allocate a lot of memory. You can stream the data from the file by outputting the lines as you read them so you don't have to hold them all in memory at once:
>>> with open("/etc/services") as f:
... for line in f:
... print(line.strip())
That method can read files of arbitrary size because it doesn't try to hold all the lines in memory at the same time.

Related

file reading in python usnig different methods

# open file in read mode
f=open(text_file,'r')
# iterate over the file object
for line in f.read():
print(line)
# close the file
f.close()
the content of file is "Congratulations you have successfully opened the file"! when i try to run this code the output comes in following form:
c (newline) o (newline) n (newline) g.................
...... that is each character is printed individually on a new line because i used read()! but with readline it gives the answer in a single line! why is it so?
r.read() returns one string will all characters (the full file content).
Iterating a string iterates it character wise.
Use
for line in f: # no read()
instead to iterate line wise.
f.read() returns the whole file in a string. for i in iterates something. For a string, it iterates over its characters.
For readline(), it should not print the line. It would read the first line of the file, then print it character by character, like read. Is it possible that you used readlines(), which returns the lines as a list.
One more thing: there is with which takes a "closable" object and auto-closes it at the end of scope. And you can iterate over a file object. So, your code can be improved like this:
with open(text_file, 'r') as f:
for i in f:
print(i)

white space added in the beginning of new line when printing in new line

When I try to print whatever data on several lines using python 3, a single whitespace gets added to the beginning of all the lines except first one. for example:
[in] print('a','\n','b','\n','c')
the output will be:
a
b
c
but my desired output is:
a
b
c
so far I've only been able to do this by doing three print commands. Anyone has any thoughts?
From the docs:
print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)
Print objects to the text stream file, separated by sep and followed by end.
sep, end, file and flush, if present, must be given as keyword
arguments.
Calling print('a', '\n', 'b') will print each of those three items with a space in between, which is what you are seeing.
You can change the separator argument to get what you want:
print('a', 'b', sep='\n')
Also see the format method.

Using a for loop to print each item of a list from an external file in Python

I am writing a program that reads a 2D list from a .txt file, and I'm trying to loop through the list, and print each item in it. I've used a for loop to loop through each item in the list. The contents of the 2D list in the .txt file is:
['1', '10']
['Hello', 'World']
This is my code so far for opening the file, reading it, and looping through each item in the list:
file = open('Original_List.txt', 'r')
file_contents = file.read()
for i in file_contents.split():
print(i)
file.close()
The output that I get from this for loop is:
['1',
'10']
['Hello',
'World']
However, the output that I'm trying to get is:
1 10
Hello World
Is there any way that I can get this output? I'm not sure how to remove the square brackets, commas and quotation marks. And once that is done, I can't figure out how to format the lines so that they are displayed as they appear in the external file (with the tabs between each item). I'm quite new to Python, so any suggestions would be great!
Splitting on newlines and outputting in your format:
from ast import literal_eval
file_contents = file.readlines() #read the file as lines
for line in file_contents:
l = literal_eval(line) #convert the string to a list
print(''.join([v.ljust(10, ' ') for v in l])) #left justify and print

IndexError: list index out of range, but list length OK

New to programming, looking for a deeper understanding on whats happening.
Goal: open a file and print the first 10 lines. (similar to head command)
Code:
with open('file') as f:
for i in range(0,10):
print([line.strip('\n') for line in f][i])
Result: prints first line fine, then returns the out of range error
File: Is a simple text file with 20 lines, no more than 50 chars per line
FYI - Removed range line and printed both type(list) and length(20). Printed specific indexes without issue (unless >1 in a row)
Able to get the desired result with different code, but trying to improve using with/as
You can actually iterate over a file. Which is what you should be doing here.
with open('file') as f:
for i, line in enumerate(file, start=1):
# Get out of the loop if we hit 10 lines
if i >= 10:
break
# Line already has a '\n' at the end
print(line, end='')
The reason that your code is failing is because of your list comprehension:
[line.strip('\n') for line in f]
The first time through your loop that consumes all of the lines in your file. Now your file has no more lines, so the next time through it creates a list of all the lines in your file and tries to get the [1]st element. But that doesn't exist because there are no lines at the end of your file.
If you wanted to keep your code mostly as-is you could do
lines = [line.rstrip('\n') for line in f]
for i in range(10):
print(lines[i])
But that's also silly, because you could just do
lines = f.readlines()
But that's also silly if you just want up to the 10th line, because you could do this:
with open('file') as f:
print('\n'.join(f.readlines()[:10]))
Some further explanation:
The shortest and worst way you could fix your code is by adding one line of code:
with open('file') as f:
for i in range(0,10):
f.seek(0) # Add this line
print([line.strip('\n') for line in f][i])
Now your code will work - but this is a horrible way to get your code to work. The reason that your code isn't working the way you expect in the first place is that files are consumable iterators. That means that when you read from them eventually you run out of things to read. Here's a simple example:
import io
file = io.StringIO('''
This is is a file
It has some lines
okay, only three.
'''.strip())
for line in file:
print(file.tell(), repr(line))
This outputs
18 'This is is a file\n'
36 'It has some lines\n'
53 'okay, only three.'
Now if you try to read from the file:
print(file.read())
You'll see that it doesn't output anything. That's because you've "consumed" the file. I mean obviously it's still on disk, but the iterator has reached the end of the file. But as shown, you can seek in the file.
print(file.tell())
file.seek(0)
print(file.tell())
print(file.read())
And you'll see your entire file printed. But what about those other positions?
file.seek(36)
print(file.read()) # => okay, only three.
As a side note, you can also specify how much to read:
file.seek(36)
print(file.read(4)) # => okay
print(file.tell()) # => 40
So when we read from a file or iterate over it we consume the iterator and get to the end of the file. Let's put your new tools to work and go back to your original code and explore what's happening.
with open('file') as f:
print(f.tell())
lines = [line.rstrip('\n') for line in f]
print(f.tell())
print(len([line for line in f]))
print(lines)
You'll see that you're at a different location in the file. And the second list comprehension produces an empty list. That's because when a list comprehension is evaluated it executes immediately. So when you do this:
for i in range(10):
print([line.strip('\n') for line in f][i])
What you're doing the first time, i = 0 and then the list comprehension reads to the end of the file. Now it takes the [0]th element of the list, or the first line in the file. But your file iterator is at the end of the file.
So now we get back to the beginning of the list and i = 1. Now we iterate to the end of the file, but we're already at the end so there are no lines to read, and we've got an empty list [] that we try to get the [0]th element of. But there's nothing there. So we get an IndexError.
List comprehensions can be useful, but when you're beginning it's usually much easier to write a for loop and then turn it into a list comprehension. So you might write something like this:
with open('file') as f:
for i, line in enumerate(file, start=10):
if i < 10:
print(line.rstrip())
Now, we shouldn't print inside a list comprehension, so instead we'll collect everything. We start out by putting what we want:
[line.rstrip()
Now add the for bit:
[line.rstrip() for i, line in enumerate(f)
And finally add the filter and our closing brace:
[line.rstrip() for i, line in enumerate(f) if i < 10]
For more on list comprehensions, this is a fantastic resource: http://treyhunner.com/2015/12/python-list-comprehensions-now-in-color/

How to print multiple lines from a file python

I'm trying to print several lines from a text file onto python, where it is outputted. My current code is:
f = open("sample.txt", "r").readlines()[2 ,3]
print(f)
However i'm getting the error message of:
TypeError: list indices must be integers, not tuple
Is there anyway of fixing this or printing multiple lines from a file without printing them out individually?
You are trying to pass a tuple to the [...] subscription operation; 2 ,3 is a tuple of two elements:
>>> 2 ,3
(2, 3)
You have a few options here:
Use slicing to take a sublist from all the lines. [2:4] slices from the 3rd line and includes the 4th line:
f = open("sample.txt", "r").readlines()[2:4]
Store the lines and print specific indices, one by one:
f = open("sample.txt", "r").readlines()
print f[2].rstrip()
print f[3].rstrip()
I used str.rstrip() to remove the newline that's still part of the line before printing.
Use itertools.islice() and use the file object as an iterable; this is the most efficient method as no lines need to be stored in memory for more than just the printing work:
from itertools import islice
with open("sample.txt", "r") as f:
for line in islice(f, 2, 4):
print line.rstrip()
I also used the file object as a context manager to ensure it is closed again properly once the with block is done.
Assign the whole list of lines to a variable, and then print lines 2 and 3 separately.
with open("sample.txt", "r") as fin:
lines = fin.readlines()
print(lines[2])
print(lines[3])

Resources