Related
Following problem is a problem from cs50 pset6. The goal here is to search for a .txt file that represent a DNA thread and check how many times a specific string occurs consecutively. If number of cons. string matches with an individual for each DNA example, print individuals name.
I am still a newbie with python, I wrote what I meant by the lines I hope all is right. Any help is appreciated. (At the moment code does not give any outputs)
python dna.py databases/small.csv sequences/2.txt (commend line arguments,1st is the csv and 2nd is txt file)
CSV files :
name,AGATC,AATG,TATC
Alice,2,8,3
Bob,4,1,5
Charlie,3,2,5
name,AGATC,TTTTTTCT,AATG,TCTAG,GATA,TATC,GAAA,TCTG
Albus,15,49,38,5,14,44,14,12
Cedric,31,21,41,28,30,9,36,44
Draco,9,13,8,26,15,25,41,39
Fred,37,40,10,6,5,10,28,8
Ginny,37,47,10,23,5,48,28,23
Hagrid,25,38,45,49,39,18,42,30
Harry,46,49,48,29,15,5,28,40
Hermione,43,31,18,25,26,47,31,36
James,46,41,38,29,15,5,48,22
Kingsley,7,11,18,33,39,31,23,14
Lavender,22,33,43,12,26,18,47,41
Lily,42,47,48,18,35,46,48,50
Lucius,9,13,33,26,45,11,36,39
Luna,18,23,35,13,11,19,14,24
Minerva,17,49,18,7,6,18,17,30
Neville,14,44,28,27,19,7,25,20
Petunia,29,29,40,31,45,20,40,35
Remus,6,18,5,42,39,28,44,22
Ron,37,47,13,25,17,6,13,35
Severus,29,27,32,41,6,27,8,34
Sirius,31,11,28,26,35,19,33,6
Vernon,26,45,34,50,44,30,32,28
Zacharias,29,50,18,23,38,24,22,9
.txt file example :
TGGTTTAGGGCCTATAATTGCAGGACCACTGGCCCTTGTCGAGGTGTACAGGTAGGGAGCTAAGTTCGAAACGCCCCTTGGTCGGGATTACCGCCATTCTAGTAGTCTAACCCCGAACGCGCTCAGGCTTTGAGTTCGCGCAGCATTAAGAAGTCCATGCCGGCACCGAATGTCCCGACGACAGGCAACCAGCACGGATACCCGCCTTGAAGGCGCAATCAGTAGGTCGAGTTACAGAGGCTCCCCCCGAGCTTGTGCTTCCATTGAGTAGGGGCTATAGATATGTAGCACTCAGGTTTAGTAGCGCCCTTTTAACAGCGAGAGCCCGCCTGGTCAGAACCGAACGGCTGATACGCGAGCTGATGGCTAGAGGATGAACACGGTCCTTCTCTTCGCTTCGATCCGGGGTAGTTTTGTAGCGAAGGATAACGCTCTGTGGATTCTCCGAGAATAATCATCAGTACGGTGTGCGTACCCTCTCTTTGATCCACGCCTGGGGCTGGACATAGTCAGGCGCATTTCATCTACTTAACCCCGGTAAGGGCCACGGGCGCGACATCTCCTTACCAGGGTTGTCTTATGCTCGCTTTTCCCAGATGATAAGCATCTCGTTGTAATGAACAGGTACCTAAGAAAACTGAGTTTCGACGACCCGTCGGCTCGTGTTCTTATCTATTGATCTAACCGAGGTGAAGCTCGCCAAAAATTTCGTAATGTAAGAGAGAAATTGAAGGGGTGAATTTTGCACTCTCGTGCATACGTCTTGCTACAATAGCAAGAGCTGTATGCGTGCGACCACTTCACTACCTCTATAGCATGCGATCTCGCAGCCCGGATTGTCGCCTCCTTTGGGCCGCAAAAACGGTATACGGACACACTGCATCTGTGAGCACGCACCAACTCGATGCGCGTAATAGGCATCTGCTCCACCCAGGGGGCAAGGGCACCTGAGGACGATCTGTTCCGAACAGTATATTTGAGCCAATGTTCTATTAGTGAAGGCAAGGTGAGGGCAACTCACACTGGTACCTCGAGGAGTAATCCGATCCATCTAAACTGGCATGCCCGTTCGAGCTCGGGGGGTTCTTGAATTTAGCTGCGTGTACCTCAGGTCTCCTGAAGGTGACACCAAAGTACAAGATAGATAGATAGATAGATAGGTAATATCTGACGTGAATTGCTTACCGCTAGTGAGCGATTTAGGTCACGTCCTCTGAAGATGTACCGTGATCATCGATGAAATGGCTCTGCAGAGCGTTGCTCTTAACTTAGTGGGAGTGTTCCTTTGCAGTCTGATGAAGTCGCTGCATGTTAACTTTGCACTAAGGGCGTTTCCGAACCCTATAGTCATCCTTATTGATTCGCCCTGTCTTACCCAGGATACACTACCGTTCGAGGCTCTTAACGTACCAACGCATGCAGTCAGAAGATGATTCACCATCCAAGCAAATCTGTCTGTCTGTCTGTCTGTCTGTCTGTCTGTCTGTCTGTCTGTCTGTCTGTCTGTCTGTCTGTCTGTCTGTCTGTCTGTCTGTCTGTCTGTGGCTTTAAAGCACCGAATGTAGTTGGCCATCGGTCTCGGTCACCAATAAGACGGCCTCGTGGGTCACTCGGTCGATGATCTAGGGTCGGGTGCATAGTGTTTCAGGTCGGCGCTCAGGGTTCTTGTCAGGGAAATCTACGGGTGAGTTGGAAAGCGCCGCCAGCGAGATGCCTGTAGGCGATTAGTGTAGAGAGAGCAACATCGGAAAATTGTCCGTGGGGCGCTACGTAAGTGTTCCCAGTATTCTCGTCCAGAGTAAGTCATGCATACCAGTATCAGGCGTCTGTGTGTTACGTTGCAGTGTATCCCGGTAGCGGGAAGCGTATAGAGCGTAACAGACCTGTCCTACAGCACGCAGGATGTCGACCCTTTCTCAGGCACGATACTTCGTGTAACAGCAGTTCCGGTGTCATCTGTAACTGTTCTGTGTTCCATAGTGAAGATATCTATCTATCTATCTATCTATCTATCTATCTATCTATCTATCTATCTATCTATCTATCTATCTATCTATCTATCTATCTATCTATCTATCTATCTATCTATCTATCTATCTATCTATCTATCTATCTATCTATCTATCTATCTATCTATCTATCTATCTATCTATCTATCTATCTATCTATCTATCTATCGGGCGACCCTGGCAATCAGGCGCCTGCTTATATGACAATTTGTCGCAATACGGGTCGCAGATGTATTGTCCGCATGAGTTTACGGTATCCGGAACTGTCACCGCCGATCCAATATGATCGCAAATCGGGGTGACACAATGGACCGCCGTAGATAAACCCTGCGATGCTGCAATAAGGATATGATATCGCGCGCGGGCCGTAAAACCGATCTTGGAAGGCGGGAAGTCTCCGGGAAAAACTCTCTGATAAAGCCTATTACAAGAAGAGCTCGAAGGCAAGATGGGCATGCCCCGTCGACCACACGGGCAAGCTCTGAGAATCGATGTGGTCGCTTAACCAACCCATACGGAGTGAACGAGACCACGCGGGCGGTTCTTGGTACGCATGATTCCTATTGGTTCTGCCGGGCGTGTGCAGGATTGTTCACTCCCCACCCTGTCGCTCACGAACGCGCTGGTTGCTTAAACCGACCGGAAATTCTGTAGCCGCCCCGTAAGTTTAACGCTTTGAAATACTCCACATGTGCGTACCGGGTCTGATCGCTTACGTGGCGCCACTATGTTAGGAGCTCATAGATATCGATGAATCAAATGTCTTTCATCGCTCCTTAAACAACCTGACGTATTCGCAAAATTGCGCGTATTGAGAAGGGAAAGTTAAAGGAACGATAACAATGAGTCTGCTTTCACCGGCTGCATAACGGGATCGCGCGCTATGGGATTTCCTAACTATAATTCGTGTCGATACTCAGACGCGTTGTACAGGTAAGAAGTCGGCGGGACAGTATTTGAGAAGGGGCTCTGCGGCACCAACGCCGAGCTGTATCAGGGGGGTTAATGTGTAGCGGGCATATAACACAATACAGCCCGCGGCGCGTCGTGGTTACCGTAGAATGAATGAATGAATGAATGAATGAATGAATGAATGAATGGAAAGAAAGAAAGAAAGAAAGAAAGAAAGAAAGAAAGAAAGAAAGAAAGAAAGAAAGAAAGAAAGAAAGAAAGAAAGAAAGAAAGAAAGAAAGAAAGAAAGAAAGAAAGAAACACCGGAGCTAGGATCCACGACTACCAGTGGGAAACTGTGAATTGTGCATGGTAATTAAAGGATGACTGGTCAACACCGGTCTCCACGGGCGTTAAACAACCTCGCTCCAGTCAATCTCTAGCGGTGGTTGTGGCAGCTTATTCCTGGAGGTAATACTCTTCCGGGCCCACTAAAAATGTAACGAAGTCGAGGTTGGGTCAGGGGATTGAGTGGGGGCGACTCACTGATTCCACCAGGAATTGTCGTCAATCGCGACGTACTTTGAGCCTTGTATCTTGGCGTTTCTTGTTGGTACGCGGCCGTGTTCGTGAATCACGACGTCGTTCATGATTCATCCGTCCAAGCCTAGACCTAGCGTAAAAACGGTGTCGATCTGTGCTCCAACCGATGGATGGTTTTTACACAAGTGAACTTCGAGGCTGTGGGACAAACAGCACAACTTGTTCACTGCTGACCGTGGTACTAAACCACGCTTGCTTTCAGCCCTTTTTTCTTTTTTTCTTTTTTTCTTTTTTTCTTTTTTTCTTTTTTTCTTTTTTTCTTTTTTTCTTTTTTTCTTTTTTTCTTTTTTTCTTTTTTTCTTTTTTTCTTTTTTTCTTTTTTTCTTTTTTTCTTTTTTTCTTTTTTTCTTTTTTTCTTTTTTTCTTTTTTTCTTTTTTTCTTTTTTTCTTTTTTTCTTTTTTTCTTTTTTTCTTTTTTTCTTTTTTTCTTTTTTTCTTTTTTTCTTTTTTTCTTTTTTTCTTTTTTTCTTTTTTTCTTTTTTTCTTTTTTTCTTTTTTTCTTTTTTTCTTTTTTTCTTTTTTTCTTTTTTTCTTTTTTTCTTTTTTTCTTTTTTTCTTTTTTTCTTTTTTTCTTTTTTTCTCAGATGCGGATCAAGGGTTACTCGAGCCGTTCTGAGGTCCTAAAATTTTAGCCCTTGGTGTTAGCTTCGGTTTAAGAACGTAGGTGCGACGCGGGGGTCCTAGAGCTCCGCGATCTGCACTCCCCACCTGGCACCAAAACGAATCCTGCATAACGGCTCTCTGTGCATGGGGGATGGTCGCAACAACGAGCATAGCTGGCATCACTTCGTTTGCTGTGGATTGCTGTTTTATACAGAATACGGTGGTGATCATCAAAGGAAGCATAATCCACATCGGGCACCCCGGGCCATCGTGCGTTCCCTTATAGCCGGCTTGCATGTTGGGGGAGGAGTAAGGCCGGTAACGTCTCGCAGCACTGTCGCGTAACACAGGTACATCTTTATTTCCGGTGCTGTAGAAGTGGTTTTTCGAAGGCGTAACCCAGAACGACTGATATAATAGTCCACTATTCCCTGGTTTAAGACTTCTACAAAGTTTTACGCAAAGTTACATGCACACTCGGCGACGTAAATATTAGCCTTGCTAAATTGCCACGGATATTAATCCCGAGCCAACCTGTTCCCACTAGCGGTCTACGGTCATAGTCCTTTGTGTAGAGCGTCATTGCGGTTGGGGCCCGTCCGCGGAGGTTCCCCTTATGATCTAACCGCGGTGCAGGTTGACTGAATGCCATACACTATAGAGAAGACGTCTAAGTAGAAACGTTCTTTAAAAATCTTGAACTGACGGCCGAGTATTATCAAGAGAGATCAGATCAGATCAGATCAGATCAGATCAGATCAGATCAGATCAGATCAGATCAGATCAGATCAGATCAGATCAGATCAGATCAGATCAGATCAGATCAGATCAGATCAGATCAGATCAGATCAGATCAGATCAGATCAGATCAGATCAGATCAGATCAGATCAGATCAGATCAGATCAGATCATGCACAATAAGGTTAGAAGCAGCAAGCATGTATTCTTTGCATAGAGGCGGTAAAGCCGCCTTGCATACCCAGCAGCAGCCGCGAAGGCCTTACTCCAGAGGACAGAACTTCTCACACAGCGTCCGCATACACCGCGGACGTGACAAGGTTAGATAGCTCTAGTTTGCGGCAACCCTCGCATCAGGCCGACTCACCCGCGCTTGCTACCCGGAGGATGGGTCAAGGGATAAACATAGCACGTTAGTTAAGCCTAACGTCAGTTTTTAGAGTTTACATGCACGACTAAGTGCATCGAAATACACGCCGTTGACAGACCAACAGCGTGTCAACTGGGCCTTGAGAATTGTATCATAATAGCCAAATACGAGGCCAAGTAGTCCGACGAGAGGCACGTAGAGACCACTTTCCCTAAACGATCTGTCGCATTACCCTTTGACTCGCACCCTATGCCTTATGTTCCAAGCAGCACCGAAGTTAGATTTAAGGGCGTATCTATCGGTACCTCGGTTGGGCCGGTCCACAGCTCCAGCTGAATTAGTGCTCACCCCGCTTCGAGGTTGAGTAAGGGTCACTTTTAAAAATATGCTTAAGGGTGATTCACATGACAGTAATCGAATAGTGAGATATAAGTAGGTGCGCCCCGCGCACACATCAAAACTGTGCAGACTGAAACTGAATGCTGGAGGCTGAGGAAAATGAAGATCAGAGTCTAGTCTAGTCTAGTCTAGTCTAGTCTAGTCTAGTCTAGTCTAGTCTAGTCTAGTCTAGTCTAGTCTAGTCTAGTCTAGTCTAGTCTAGTCTAGTCTAGTCTAGTCTAGTCTAGAGAAGAGTGAATGAATAGATCTGCCGCTGAATCCCCGCGTGAGGTTTTTGCGAC
Code:
from sys import argv
import csv
from itertools import groupby
#first csv cma 2nd txt
# fread from CSV file first thing in a row is name then the number of strs
# fread from dna seq and read it into a memory
#find how many times each str censequetivel
# if number of strs == with a persons print the person
checkstr = [] #global array that tells us what str to read
def readtxt(csvfile,seq):
with open(f'{csvfile}','r') as p:#finding which str to read from header line of the csv
header = csv.reader(p) # Header contains which strs to look for
for row in header:
checkstr = row[1:]
break
with open(f'{seq}','r') as f:#searching the text for strs
s = f.read()
for c in checkstr:
groups = groupby(s.split(c))
try:
return [sum(1 for _ in group)+1 for label, group in groups if label==''][0]
except IndexError:
return 0
def readcsv(n):
with open(f'{n}','r') as f:
readed = csv.DictReader(f)
for row in readed:
return row
def main():
counter = 0
if len(argv) != 3:
print("Please start program with cmd arguments.")
readtxt(argv[1], argv[2])#for fulling the checkstr
for i in range(0,len(checkstr)): #Do this as much as the number of special strings
for j in checkstr: #For each special string in the list
if readtxt(argv[1], argv[2]) == readcsv(argv[1])[f'{checkstr[j]}']: #If dictionary value that returns for that spesific str is matches to the spesific str
counter += 1
if counter == len(checkstr): # if all spesific strs matches, then we found our person!
print(readcsv(argv[1])['name'])
#readtxt(argv[1], argv[2])
#readcsv(argv[1])
main()
I think the answer quite simple: you forgot an else-statement.
After you check the number arguments, you must place the else-statement.
def main():
counter = 0
if len(argv) != 3:
print("Please use: program <csvfile> <textfile>") # give usage and exit
else:
readtxt(argv[1], argv[2])#for fulling the checkstr
for i in range(0,len(checkstr)): #Do this as much as the number of special strings
for j in checkstr: #For each special string in the list
if readtxt(argv[1], argv[2]) == readcsv(argv[1])[f'{checkstr[j]}']: #If dictionary value that returns for that spesific str is matches to the spesific str
counter += 1
if counter == len(checkstr): # if all spesific strs matches, then we found our person!
print(readcsv(argv[1])['name'])
#readtxt(argv[1], argv[2])
#readcsv(argv[1])
main()
I am trying to write a function that will allow the user to enter a name or phone number, check if it is present in a file, and if it is prints out the entire line in which that element has been found. I have so far:
def searchPlayer():
with open("players.txt") as f:
data = f.readlines()
print "Enter 0 to go back"
nameSearch = str(raw_input("Enter player surname, forname, email, or phone number: "))
if any(nameSearch in s for s in data):
#Finding the element in the list works
#Can't think of a way to print the entire line with the player's information
else:
print nameSearch + " was not found in the database"
The file is formatted like so:
Joe;Bloggs;j.bloggs#anemailaddress.com;0719451625
Sarah;Brown;s.brown#anemailaddress.com;0749154184
So if nameSearch == Joe, the output should be Joe;Bloggs;j.bloggs#anemailaddress.com;0719451625
Any help would be appreciated, thank you
Why not use a loop?
for s in data:
if nameSearch in s:
print s
break
any is looping anyway, from the docs:
def any(iterable):
for element in iterable:
if element:
return True
return False
Seems too complicated, just do
with open("players.txt") as f:
for line in f:
if nameSearch in line:
print line
You can't use any as others have mentioned, but you can use next if you want to keep the more compact code. Instead of:
if any(nameSearch in s for s in data):
you'd use next with a default value:
entry = next((s for s in data if nameSearch in s), None)
if entry is not None:
print entry,
else:
print nameSearch, "was not found in the database"
Note: You might want to use csv.reader or the like to parse here, as otherwise you end up mistaking formatting for data; if a user enters ; you'll blindly return the first record, even though the ; was formatting, not field data. Similarly, a search for Jon would find the first person named Jon or Jonathan or any other name that might exist that begins with Jon.
As #alexis mentioned in a comment, you shouldn't use any() if you want to know which line matched. In this case, you should use a loop instead:
found = False
for s in data:
if nameSearch in s:
print s
found = True
#break # Optional. Put this in if you want to print only the first match.
if not found:
print "{} was not found in the database".format(nameSearch)
If you want to print only the first match, take out the hash sign before break and change if not found: to else:.
This is python and I am using idle version 3.4.2.
So at the moment my code works but I would like to adapt it to be able to:
Save the most recent three scores for the name (as they re-run the code and the scores are saving in the text file). However there is an issue that whatever "name" is entered, it re saves on its own line with the score, rather than "appending" (I know this is because it's not saved in the form of a list/dictionary, but how would I do that? - or I read that you can "split" the line?)
That is my first question and if anyone can help I would be so hugely appreciative, I am new to python so this is ab ig challenge for me! Any comments or suggestions are very welcome!!
import random #import module
print("What is your name?") #prints writing in brackets
name = input().title() #Capitalizes the first letter of the word inputted
print("What class are you in? (Enter 1, 2 or 3)") #asks the user to input a number
while True:
try:
class_number = int(input()) #asks for an integer input from user
except ValueError:
print("Sorry, I didn't understand that, please try again") #print statement
continue
if class_number > 3: #if input is more than 3
print("SORRY but that class isn't recognised, try again") #print statement
continue
else:
print ("Hello,", name, "from class", class_number, "welcome to my quiz") #prints writing in brackets and anything saved in the variable "name" and "class_number"
break #break out of loop
score = 0 #sets the variable "score" to zero
question = 0 # sets the variable "question" to zero
while question < 3:#If questions (intitally set to 0) is smaller than 10, carry out this function
question +=1 # add one to the value of "question"
maths = random.randint(1,3) #randomly generate a number from 1-3 and store as "maths"
num1 = random.randint(1,10)#randomly generate an integer from 1-10 and store as "num1"
num2 = random.randint(1,10)#randomly generate a second integer from 1-10 and store as "num2"
if maths == 1: #if the number generated is 1
print(num1, "+", num2) #prints num1 + num2
ans = num1 + num2 #sets "ans" to equal the value of num1 added to num2
elif maths == 2: #if the number generated is 1
print(num1, "*", num2) #print num1 multiplied by num2
ans = num1 * num2 #sets "ans" to equal the value of num1 multiplied by num2
else: #else run this part of code
print(num1, "-", num2) #print num1 subtracted by num2
ans = num1 - num2 #sets "ans" to equal the value of num1 subtracted by num2
while True:
try:
user_ans = int(input()) #user inputs answer to question
except ValueError: #runs when the user input is no an integer
print ("SORRY but that answer isn't recognised, try again")
else:
break
if user_ans == ans:
score+=1
print("Well done, you are CORRECT")
else:
print("SORRY, you are INCORRECT") #print writing in brackets
print("The correct answer was", ans)
if score == 10: #run this part of code if "score" equals 10
print("fantastic", name, "you got full marks!") #print statement and name
elif score >= 6: #run this part of code if "score" is larger than or equal to 6
print("well done, there's some improvement to be done here though", name, "you got", score, "/10")# then print statement and score
elif score <=5: #run this part of code if "score" is smaller than or equal to 5
print("hmm, maybe some more practise would be beneficial", name, "you got", score, "/10") #then print statement and score
class_number = str(class_number) + ".txt" #this adds '.txt' to the end of the file (therefore creating a text file) so it can be used to create a file under the name of the class
file = open(class_number, 'a') #opens the file in 'append' mode so you don't delete all the information
file.write(str(name + " : ")) #writes the name and ":" to file
file.write(str(score)) #writes the score to file
file.write('\n')#writes the score to the file
file.close()#safely closes the file to save the information
view = int(input("would you like to view the scores? If yes, press 1 or not press 2"))
if view == 1:
exit
elif view == 2:
exit #to be completed
If you want to keep it human readable write it in a json file:
import json
your_dictonary = {"my_key":"one_value"}
str_to_save = json.dumps(your_dictonary)
# Then write it to a file as you did before
Loading is almost as easy:
json.loads(file_content) # after you read the file as usual
If you want to save the user's score to a list...
my_list = []
my_list.append(score)
You may want to read in the file before the game starts as well. Then, you will need to populate the list with scores that are in the text file.
with open(class_number) as scorefile:
for line in scorefile:
my_list.append(line)
Finally, when the game ends you'll want to add the user's score to the file. In this case, I'll keep it simple and not include the person's name for an example, you can still add the line to the list though.
f = open(class_number 'w')
f.write("\n" + score)
f.close()
And then if they view the scores, just print off the value of my_list, separating each element in the list by a new line.
Use the pickle module to store your data. Organise your user => score relation into an dictionary, then call pickle.dump(filename, theDict) to save it to a file.
When you need it back, call theDict = pickle.load(filename) and it will load the data from the pickle file. This approach is better than you having to devise your own parsing algorithm.
If you're ok with changing the look of your file, try saving the file as json.
At the top of your code, load in the scores from the file:
import json
with open('{}.txt'.format(class_number)) as f:
scores = json.load(f)
Then you can modify scores in your dictionary and write back to the file:
scores[name] = score
with open('{}.txt'.format(class_number)) as f:
json.dump(scores, f)
This code doesn't store more than the latest score, but you can explore options for saving more than one score per name. I suggest taking a look at defaultdict.
Some answers suggest storing the scores as JSON (good idea) or pickling them (bad idea! it's dangerous). This answer assumes you want to keep the flat-file, oldest-first format.
You're opening the file in append mode, so you won't be able to change any of the content. To make changes, you'll first need to read from the file:
try:
fileh = open(class_number, 'r')
oldlines = fileh.readlines()
fileh.close()
except IOError: # If we didn't find the file, there were no old scores
oldlines = []
Note that this reads all the lines; if your file grows very large, it won't all fit into memory and you should read line-by-line and write as you go.
For each line:
If it's another person's score, you have no reason to touch it, just write it back verbatim.
If it's this person's score, keep it iff it's one of the two most recent.
It's slightly easier to keep track of the most-recent scores if we start with the most recent line, so let's do that:
updatedlines = []
recentscores = 0
for line in oldlines[::-1]: # go backwards, most recent line first
(lname, lscore) = line.split(" : ") # read the name and the score from the line; this will break if the name contains " : "
if lname == name:
recentscores += 1 # keep track of how many scores we have for this person
if recentscores <3:
updatedlines.append(line)
else:
updatedlines.append(line)
updatedlines = updatedlines[::-1] # put the lines back in the right order
Finally, add the new score.
updatedlines.append("%s : %d\n" % (name, score))
Now we can write the lines back to the file:
fileh = open(class_number, 'w')
fileh.writelines(updatedlines)
fileh.close()
I'm not going to lie. I'm trying to do an assignment and I'm being beaten by it.
I need to have python prompt the user to enter a room number, then lookup that room number in a supplied .txt file which has csv [comma-separated values], and then show multiple results if there are any.
I was able to get python to return the first result ok, but then it stops. I got around the csv thing by using a hash command and .split (I would rather read it as a csv although I couldn't get it to work.) I had to edit the external file so instad of the data being seperated by commas it was seperated by semicolons, which is not ideal as I am not supposed to be messing with the supplied file.
Anyhow...
My external file looks like this:
roombookings.txt
6-3-07;L1;MSW001;1
6-3-07;L2;MSP201;1
6-3-07;L3;WEB201;1
6-3-07;L4;WEB101;1
6-3-07;L5;WEB101;1
7-3-07;L1;MSW001;2
7-3-07;L2;MSP201;2
7-3-07;L3;WEB201;2
7-3-07;L4;WEB101;2
7-3-07;L5;WEB101;2
8-3-07;L1;WEB101;1
8-3-07;L2;MSP201;3
Here's what my code looks like:
roomNumber = (input("Enter the room number: "))
def find_details(id2find):
rb_text = open('roombookings.txt', 'r')
each_line = rb_text.readline()
while each_line != '':
s = {}
(s['Date'], s['Room'], s['Course'], s['Stage']) = each_line.split(";")
if id2find == (s['Room']):
rb_text.close()
return(s)
each_line = rb_text.readline()
rb_text.close()
room = find_details(roomNumber)
if room:
print("Date: " + room['Date'])
print("Room: " + room['Room'])
print("Course: " + room['Course'])
print("Stage: " + room['Stage'])
If i run the program, I get prompted for a room number. If I enter, say, "L1"
I get:
Date: 6-3-07
Room: L1
Course: MSW001
Stage: 1
I should get 3 positive matches. I guess my loop is broken? Please help me save my sanity!
Edit. I've tried the solutions here but keeps either crashing the program (I guess I'm not closing the file properly?) or giving me errors. I've seriously been trying to sort this for 2 days and keep in mind I'm at a VERY basic level. I've read multiple textbooks and done many Google searches but it's all still beyond me, I'm afraid. I appreciate the assistance though.
Your code does "return(s)" the first time the "id2find" argument is exactly equal to the room.
If you want multiple matches, you could create an empty list before entering the loop, append every match to the list WITHOUT returning, return the list, and then use a for-loop to print out each match.
First. For iterating over lines in the file use next:
for line in rb_text:
# do something
Second. Your function returns after first match. How can it match more then one record? Maybe you need something like:
def find_details(id2find):
rb_text = open('roombookings.txt', 'r')
for line in rb_text:
s = {}
(s['Date'], s['Room'], s['Course'], s['Stage']) = line.split(";")
if id2find == (s['Room']):
yield s
rb_text.close()
And then:
for room in find_details(roomNumber):
print("Date: " + room['Date'])
print("Room: " + room['Room'])
print("Course: " + room['Course'])
print("Stage: " + room['Stage'])
And yes, you better use some CSV parser.
Your problem is the return(s) in find_details(). As soon as you have found an entry, you are leaving the function. You do not even close the file then. One solution is to use an empty list at the beginning, e.g results = [], and then append all entries which matches your requirements (results.append(s)).
Im stuck on a problem for an assignment, I need to write a program that opens a file on my computer, and scans that file for the first instance of a number. Once it is found it will return
The first number in , filenm is x
otherwise it will say there is no number in filenm.
My code so far is below:
When i run it no matter what it always says theres no number :(
filenm = raw_input("Enter a file name: ")
datain=open(filenm,"r")
try:
c=datain.read(1)
result = []
for line in datain:
c=datain.read(1)
while int(c) >= 0:
c = datain.read(1)
result.append(c)
except:
pass
if len(result) > 0:
print "The first number is",(" ".join(result))+" . "
else:
print "There is no number in" , filenm + "."
That's all you need:
import re
with open("filename") as f:
for line in f:
s=re.search(r'\d+',line)
if s:
print(s.group())
break
open the file;
read it in a loop char-by-char;
check if the char is digit, print whatever you want;
it means there are no numbers in the file, if end-of-file is reached, print "no numbers"
Use <string>.isdigit() method to check if the given string (a single character in your case) is a digit.
I don't recommend mixing iterating through a file
for line in datain:
with using the read method (or any similar one)
c=datain.read(1)
Just stick with one or the other. Personally, I would go with iterating here.
readlines() method returns a list of all the lines in the file. You can then iterate trough the list of characters in each line:
filenm = raw_input("Enter a file name: ")
datain=open(filenm,"r")
try:
result = []
for line in datain.readlines():
print 'line: ' + line
for each in line:
try:
# attempt casting a number to int
int(each)
# if it worked it add it to the result list
result.append(each)
except:
pass
except:
pass
print result
if len(result) > 0:
print "The first number is",(" ".join(result[0]))+". "
else:
print "There is no number in" , filenm + "."
This will only work with the first number character it finds, not sure if you actually need to extract multi digit numbers.
My thoughts:
1) As others noted, don't mask the exception. It would be better to let it be thrown - at least that way you find out what went wrong, if something went wrong.
2) You do want to read the file a line at a time, using for line in file:. The reason for this is that the numbers you want to read are basically "words" (things separated by spaces), and there isn't a built-in way to read the file a word at a time. file.read(1) reads a single byte (i.e. character, for an ASCII file), and then you have to put them together into words yourself, which is tedious. It's much easier to tell Python to split a line into words. At least, I'm assuming here that you're not supposed to pick out the "20" from "spam ham20eggs 10 lobster thermidor".
.readlines() is somewhat redundant; it's a convenience for making a list of the lines in the file - but we don't need that list; we just need the lines one at a time. There is a function defined called .xreadlines() which does that, but it's deprecated - because we can just use for line in file:. Seriously - just keep it simple.
3) int in Python will not return a negative value if the input is non-numeric. It will throw an exception. Your code does not handle that exception properly, because it would break out of the loop. There is no way to tell Python "keep going from where you threw the exception" - and there shouldn't be, because how is the rest of the code supposed to account for what happened?
Actually your code isn't too far off. There are a number of problems. One big one is that the try/except hides errors from you which might have help you figure things out yourself. Another was that you're reading the file with a mixture of a line at a time (and ignoring its contents entirely) as well as a character at a time.
There also seems to be a misunderstand on your part about what the int() function does when given a non-numeric character string, what it does is raise an exception rather than returning something less than 0. While you could enclose a call to it it in a try/except with the except being specifically for ValueError, in this case however it would be easier to just check ahead of time to see if the character is a digit since all you want to do is continue doing that until one that isn't is seen.
So here's one way your code could be revised that would address the above issues:
import string
filenm = raw_input("Enter a file name: ")
datain = open(filenm,"r")
# find first sequence of one or more digits in file
result = []
while True:
c = datain.read(1)
while c in string.digits: # digit?
result.append(c)
c = datain.read(1)
if c == "" or len(result) > 0: # end-of-file or a number has been found
break # get out of loop
if len(result) > 0:
print "The first number is'", "".join(result) + "'."
else:
print "There is no number in'", filenm + "'."
close(datain)