Python Forum

Full Version: [Python3] Trailing newline in readlines.
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
I seem to have having an issue with trailing newlines when reading in a file.

Steps to reproduce the problem:

(1. Create a file with newlines.
(2. Read in file as an array with readlines.
(3. Sample array with random.
(4. Print sample array to screen.

What seems to get printed is:

Hello World\n.

And not:

Hello World. I have to use static data ( directly hard coded data ) in order to use it.

My use case:

I tend to read version numbers from a file, and use that version number to choose an item from an array. I don't want a newline symbol also being printed.

The error is from readlines().

Is it an issue with random, or something else?

This seems to work fine though:

# Import necessary modules.
import os
import random
import time
 
# Clear the screen
os.system("clear")

# Create a datasheet of pet varieties.
pets = [
  "cat",    "dog",     "rat",
  "gerbil", "hamster", "guiniepig",
  "monkey", "snake",
]

# Create a datasheet of interior varieties.
interior = [
  "bedroom",     "closet",  "bathroom",
  "hallway",     "kitchen", "living room",
  "dining room", "garage",
]

# Create a datasheet of exterior varieties.
exterior = [
  "outhouse", "driveway", "frontyard",
  "backyard", "fence",
]

# Create pet string from pet sample stripping brackets.
sample_pets = random.sample(pets, k = 1)
active_pet = str(sample_pets).strip("[]''")

# Create interior string from interior sample stripping brackets.
sample_interior = random.sample(interior, k = 1)
active_interior = str(sample_interior).strip("[]''")

# Create exterior string from exterior sample_interior stripping brackets.
sample_exterior = random.sample(exterior, k = 1)
active_exterior = str(sample_exterior).strip("[]''")

# Display ai result symbolically.
print(active_pet + "(" + active_interior + ", " + active_exterior + ")\n")

file = open("data.txt", "w")

file.write("I have an animal in my"              + active_interior +
           ". The animal within my house is my " + active_pet      +
           ". Therefore, it is my "              + active_pet      +
           " that is in my "                     + active_exterior +
           ".\n")

file.close()
This performs as I expect it without the trailing newlines.

I'm more used to Ruby, where reading in a file doesn't cause the newline to actually show up. I read in files a lot for things like using version numbers to pick an item in an array.
this is not an error, but expected behavior with readlines. Every line in the text file will have trailing new line '\n'
use str.strip() method to remove it - iterate over the list returned from random and strip the new lines from every element.

as a side note, this:
active_pet = str(sample_pets).strip("[]''")
is not he way to construct comma separated list of strings. use str.join method
Figured it out I think.

f = open("array.txt", "r")

display = f.readlines()

print(display[0])
Only wanting to print a part of a list, not show the entire thing.
(Mar-09-2020, 10:13 PM)LWFlouisa Wrote: [ -> ]Figured it out I think.
Not really. When printing any of the elements in display you will not see \n at the end like you do in a list, where you see the representation of the str, incl. non-printing chars like new line, tab, etc. But it's there and as a result you will see an extra blank line after the output - one from the string itself and one from the print function.
It really depends what you want to do with the lines from the file - do you just print them (in which case you can just pass end='' argument to print function in which case you will avoid the extra new line. Or you want to process/use them in some way, in which case you need to strip the new line from the end of the string.

sample.txt
Output:
dog cat
with open('sample.txt') as f:
    content = f.readlines()
print(content)
for line in content:
    print(line)

# how to strip new line
print('\n-----')
with open('sample.txt') as f:
    content = [line.strip() for line in f]

print(content)
for line in content:
    print(line)
Output:
['dog\n', 'cat\n'] dog cat ----- ['dog', 'cat'] dog cat
I observe some things that can be improved (by my subjective opinion).

1. Get random item from list -> use random.choice. Benefits: only one item is needed, returns item (string) right away. Use sample when more than one random item is needed.

>>> pets = ['cat', 'dog', 'rat', 'gerbil', 'hamster', 'guiniepig', 'monkey', 'snake']
>>> random.choice(pets)
'dog'
2. To construct string from different parts -> use f-strings. Benefits: better visual readability, no need for type conversion (if any). Requires 3.6 <= Python.

# Display ai result symbolically.
>>> print(f'{active_pet} ({active_interior}, {active_exterior})\n')
3. Open files -> use with context manager (as in buran examples). Benefits: file will be always properly and automagically closed, no need for close().

with open('data.txt', 'w') as f:
4. Get only first row in file -> use built-in next(). Benefits: whole file content will not be read into memory/list to just get first row. Grab first row from existing fileobject and you are done.

with open('data.txt', 'r') as f:
    my_data = next(f).strip()           # strips newline at the end, can be omitted.