I have a text file as follows:
Steve, assign tasks
Bob, register users
Using the code:
for n in textfile:
strip_task = n.strip()
split_task = n.split(", ")
read_tasks = "\n"
read_tasks += f"Task: \t{split_task[1]}"
It prints 'register users'
But I need it to also print the second line from the first sentence.
It seems to be only be reading from the second line in the text document even though after printing 'textfile' as its own it'll print the whole file as:
['Steve, assign tasks\n', 'Bob, register users']
I've checked the length of the text doc and it's reading as two so why is it only reading once in the for loop.
The problem is that you overwrite the variable read_tasks in each iteration.
You can solve the problem by defining the variable outside the loop as an empty string, and then add strings to the variable in the for loop:
read_tasks = ""
for n in textfile:
strip_task = n.strip()
split_task = n.split(", ")
read_tasks += "\n"
read_tasks += f"Task: \t{split_task[1]}"
Related
very new to Python and having a weird issue which I can't find a solution for online.
I need to take a binary file containing data and display it in a table format, which is almost working except that it pushes the end of the first line to the next and throwing everything off as shown below.
Table print issue
Code for the function to view the binary file data as below.
As its for an assignment I don't think I can use 3rd party table modules like tabulate so this was my attempt at just doing it with string formatting. It was moving the end of the each line to the next when printing with an entire empty line so I added the end=' ' bit to the print statement but still no dice. There's probably an easier way of displaying the data as a table anyway but I'd be happy with it if I could just figure out why it won't stay on one line when printing the data under the headers :|
def functionRetrieve():
while True:
filename = input("Please enter a binary file name:")
try:
open(filename + ".bin", 'r')
except FileNotFoundError:
print("Wrong file name or file type")
else:
break
filename = filename + ".bin"
print("\033[4m|{:^24}|{:^24}|{:^14}|{:^14}|{:^14}|{:^14}|\033[0m".format("Last Name", "First Name", "Games Played", "Total Points", "Average", "Position"))
with open(filename, 'rb') as textfile:
for line in textfile:
line = line.decode('utf-8')
data = list(line.split(","))
lastname = data[0]
firstname = data[1]
gamesplayed = data[2]
totalpoints = data[3]
average = data[4]
position = data[5]
print("|{:^24}|{:^24}|{:^14}|{:^14}|{:^14}|{:^14}|".format(lastname, firstname, gamesplayed, totalpoints, average, position), end='')
with end='' you're overwriting the default end value of print from newline '\n' to ''. So basically you're printing one loooong line instaed of multiple lines. Thats why each new print seems to be with one additional space indent. The lines are appending instead of printing below eachother.
In your header row you do not do this, that is why the first row looks "normal". This should fix it:
print("|{:^24}|{:^24}|{:^14}|{:^14}|{:^14}|{:^14}|".format(lastname, firstname, gamesplayed, totalpoints, average, position))
I have a file with data about students such as their name, address, grades, etc. I created a function that would delete a whole line from a text file based on a student's First Name and Last Name. This function worked correctly. However, afterward, I decided to update it so that if the user entered a name that was not in the file it would print: Student not found. However, now even, if the user types in a name that is in the file it still prints: student not found...
Here is my code:
def delete_a_record(filename):
x=input("Remove First Name:")
y=input("Remove Last Name:")
with open(filename, "r") as f:
lines = f.readlines()
with open(filename, "w") as f:
for i in lines:
t=i.split()
if t[0]!=x and t[1]!=y:
f.write(i)
elif x or y not in t:
print("Student Not Found")
f.close()
delete_a_record("mytextfile.txt")
Could someone explain to me why?
For what I undestood(correct me if I'm wrong), I guess there is two issues in your logic.
If you mean to test if both x and y are not in t you should test it separatelly, like:
if t[0]!=x and t[1]!=y:
f.write(i)
elif x not in t and y not in t:
print("Student Not Found")
The way it is now, if x is not None, the condition elif x or ... will always return true because x evaluates to True.
If you want to check if the student is not in the entire file, I think you should not be testing this for each line you read. Since you don't know in which line the student might be, maybe you could reorganize your code to process the whole file first before testing if the student was not found.
Probably because you are iterating line by line, so even if the name is in the .txt file every time the name doesn't match the current line it will print "Student Not Found". You need to rewrite you function so that the print statement is only made when the lines have been exhausted and the name has not been found.
If You Want to Use Your Function And Search In That (You Don't Want to Change Your Function) You Can Put Your Data In A List And Search In That List Like Below Code:
list=['f_Name = Lorem','l_Name = Ipsum']
if "f_Name = "+x in list or "l_Name = "+y in list:
print("True")
else:
print("Student Not Found")
I have a file containing:
name: Sam
placing: 2
quote: I'll win.
name: Jamie
placing: 1
quote: Be the best.
and I want to read the file through python and append specific contents into a list. I want my first list to contain:
rank = [['Sam', 2],['Jamie', 1]]
and second list to contain:
quo = ['I'll win','Be the best']
first off, i start reading the file by:
def read_file():
filename = open("player.txt","r")
playerFile = filename
player = [] #first list
quo = [] #second list
for line in playerFile: #going through each line
line = line.strip().split(':') #strip new line
print(line) #checking purpose
player.append(line[1]) #index out of range
player.append(line[2])
quo.append(line[3])
I'm getting an index out of range in the first append. I have split by ':' but I can't seem to access it.
When you do line = line.strip().split(':') when line = "name: Sam"
you will receive ['name', ' Sam'] so first append should work.
The second one player.append(line[2] will not work.
As zython said in the comments , you need to know the format of the file and each blank line or other changes in the file , can make you script to fail.
You should analyze the file differently:
If you can rely on the fact that "name" and "quote" are always existing fields in each player data , you should look for this field names.
for example:
for line in file:
# Run on each line and insert to player list only the lines with "name" in it
if ("name" in line):
# Line with "name" was found - do what you need with it
player.append(line.split(":")[1])
A few problems,
The program attempts to read three lines worth of data in a single iteration of the for loop. But that won't work, because the loop, and the split command are parsing only a single line per iteration. It will take three loop iterations to read a single entry from your file.
The program needs handling for blank lines. Generally, when reading files like this, you probably want a lot of error handling, the data is usually not formatted perfectly. My suggestion is to check for blank lines, where line has only a single value which is an empty string. When you see that, ignore the line.
The program needs to collect the first and second lines of each entry, and put those into a temporary array, then append the temporary array to player. So you'll need to declare that temporary array above, populate first with the name field, next with the placing field, and finally append it to player.
Zero-based indexing. Remember that the first item of an array is list[0], not list[1]
I think you are confused on how to check for a line and add content from line to two lists based on what it contains. You could use in to check what line you are on currently. This works assuming your text file is same as given in question.
rank, quo = [], []
for line in playerFile:
splitted = line.split(": ")
if "name" in line:
name = splitted[1]
elif "placing" in line:
rank.append([name, splitted[1]])
elif "quote" in line:
quo.append(splitted[1])
print(rank) # [['Sam', '2'],['Jamie', '1']]
print(quo) # ["I'll win",'Be the best']
Try this code:
def read_file():
filename = open("player.txt", "r")
playerFile = filename
player = []
rank = []
quo = []
for line in playerFile:
value = line.strip().split(": ")
if "name" in line:
player.append(value[1])
if "placing" in line:
player.append(value[1])
if "quote" in line:
quo.append(value[1])
rank.append(player)
player = []
print(rank)
print(quo)
read_file()
I am trying to print a specific line from the file "Scores", which is option B. This is my code:
print("Option A: Show all scores\nOption B: Show a record\nOption Q: Quit")
decision = input("Enter A, B, C or Q: ")
myFile = open("Scores.txt", "rt")
if decision == "A":
record = myFile.read()
print(record)
myFile.close()
elif decision == "B" or decision == "b":
playerName = input("Enter a player name to view their scores: ")
record = myFile.read()
answer = record.find(playerName)
for line in answer:
print(line)
elif decision == "Q" or decision == "q":
exit
I went for Option B, then I entered a player name that holds the score of the player, but it throws this error message:
line 12, in <module>
for line in answer():
TypeError: 'int' object is not callable
A few cents from my side :
file = open("file")
lines = file.readlines()
for line in lines:
if playername in line:
print line
file.close()
Hope it works!
find() method returns a positive index if it succeeds, -1 otherwise
You should loop on your content line by line, as follows:
for line in myFile:
if line.find(playerName):
print(line)
A safer way to read the file and find data, so that you will not have OutOfMemory issues when storing the whole file in memory.
playerName = input("Enter a player name to view their scores: ")
with open("Scores.txt", 'r') as f:
for row in f:
if playerName in row:
print row
This way you will be using with that will close the file by itself either when the program ends or Garbage Collection kicks in. This way python will read the file line by line and store only 1 line in memory. So you can use huge files and do not worry about memory issues.
Hope it helps :)
Working with str methods will take more acrobatics. Try the following,
import re
p = re.compile(r"\b{}\b".format(playername)) # keep it ready
# inside option B
for line in myfile: # no need to `.read()` it
match = p.search(line)
if match:
print(line)
break # if there is only one record for playername
See if it works for you.
similar thing here:
Reading specific lines only (Python)
fp = open("file")
for i, line in enumerate(fp):
if line == playername:
print line
fp.close()
I also notice you don't close your file for each decision, should make that happen.
Few python idioms and small optimization
Here are many answer, my sample brings in few python idioms and optimize it a bit:
fname = "Scores.txt"
player_name = "Quido"
with open(fname) as f:
for line in f:
if player_name in line:
print line
break
print "Going on doing following tasks."
The with block will close the open file on exiting the inner block. No need to f.close(), safe
in case of problems to read the file.
for line in f: shows, that iterating over file open in text mode we get one line per iteration.
break after we print the line with the player will effectively stop iterating over lines assuming,
there is only one such line or that we are happy with the very first one. If this is not the case,
removing the break allows printing all lines containing the player name.
As lines returned from text file iterator contain new line, you may prefer to get rid of them. Use
print line.strip() in such case what will remove all blank characters from start and end of the line.
Final print is proving, the program continues after it processes all the lines.
It may happen, that you get no output for name, which appears to be present in the file. In such a
case, you might need to clarify letter case. For example, if your text file contains all the names
in exact casing, you have to enter the name properly.
Other option is to lower-case the player_name and compare it against lower cased line:
fname = "Scores.txt"
player_name = "Quido"
normalized_player_name = player_name.lower()
with open(fname) as f:
for line in f:
if normalized_player_name in line.lower():
print line.strip()
break # comment out to print all lines with the player
print "Going on doing following tasks."
Note, that we normalize the player_name outside from the loop to be a bit faster. Lower-casing inside the
loop would work, but would do the same task repeatedly.
The line is printed using exact letter cases as in the file.
Not sure what im doing wrong here? the program asks for file name and reads the file but when it come to printing the encoded message it comes up blank. What am I missing, as if I change the phrase to just normal raw_input("enter message") the code will work, but this is not reading from the txt file.
letters = "a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"]
cshift = int(input("Enter a number: "))
phrase = open(raw_input("file name: "), 'r')
newPhrase = ""
for l in phrase:
if l in letters:
pos = letters.index(l) + cshift
if pos > 25:
pos = pos-26
newPhrase += letters[pos]
else:
newPhrase += " "
print(newPhrase)
The problem here is that the for-loop on this line:
for l in phrase:
will return complete lines, not individual characters.
As such you will have to loop through individual characters from those lines as well, or read the file binary, or use functions on the file object that will read one character at a time.
You could simply do this:
for line in phrase:
for l in line:
... rest of your code here
The open function does not return a string, but a handle to the opened file from which strings can be read. You should search for information on how to read a file into a string in Python and then try it in a REPL to make sure it returns a string and not something else.