Python File Functions - python

I am working on a pointless guessing game for skill development. I decided to write code to read users and their scores from a file, then write a function to check whether there username is currently in the file already:
import getpass
user = getpass.getuser()
def userExists(username):
f = open('score.txt', 'rU')
for line in f:
row = line.split('\r\n')
info = row[0].strip('\r\n').split(':')
username = info[0]
if user==username:
uExists = True
break
else:
uExists = False
return usExists
f.close()
At first I had the return values, True and False inside the loop which caused problems, so I set a variable to the value and return that instead.
The score.txt looks like and uses the format of:
user:10:50
userB:5:10
But whenever I use this function userExists('nonExistingUser') it always returns True regardless if the user exists or not, any ideas what I'm doing wrong?

Your logic is a little cluttered, so first I present a slightly cleaned-up version whose operation should (if I am correct) be pretty much the same.
import getpass
user = getpass.getuser()
def userExists(username):
f = open('score.txt', 'rU')
for line in f:
username = line.rstrip().split(':')[0]
if user==username:
return True
return False
f.close()
The rstrip() method call returns the same string without any trailing whitespace; the split() call returns a list of the three strings separated by colons, and you already know what the [0] does.The uexists flag turns out to be unnecessary. I presumed you wanted to remove all white space from the end of the line?
This does have the unfortunate problem that the file never gets closed (as does your suggested code). A relatively easy (but rather advanced) fix is to use the file as a context manager.
import getpass
user = getpass.getuser()
def userExists(username):
with open('score.txt', 'rU') as f:
for line in f:
username = line.rstrip().split(':')[0]
if user==username:
return True
return False
This ensures that no matter how the function returns the file will be properly closed without needing to explicitly call its close() method.

In addition to what JAvier pointed out, you're also setting uExists but returning usExists it should be along these lines:
def userExists(username):
f = open('score.txt', 'rU')
uExists = False
for line in f:
row = line.split('\r\n')
info = row[0].strip('\r\n').split(':')
if user==info[0]:
uExists = True
break
else:
uExists = False
f.close()
return uExists
Depending upon your version of python, I'd also look into the with statement to clean up that f.close().

Use files with the with statement, that way the file is automatically closed when you exit the with block even if you leave it with an exception or a return statement.
def userExists(username):
with open('score.txt', 'rU') as f:
for line in f:
if line[:line.find(':')] == username:
return True
return False

You could simplify userExists like so:
def userExists(username):
with open('score.txt','rU') as score:
return username+':' in score.read()
You may wish to use a regular expression instead of username+':'

Related

My python function won't write to a file

I've made a function for a flask application to create a decorator and a function and then write them to a file but when I run it, it doesn't create a file and write to it and it doesn't return any errors.
def make_route(title):
route = "#app.route(/%s)" %(title)
def welcome():
return render_template("%s.html" %(title))
return welcome
f = open('test1.txt', 'w')
f.write(route, '/n', welcome, '/n')
f.close()
make_route('Hi')
A return statement terminates execution of the function, so any code after it is ignored. Also, write writes a string, not random objects. You want:
def make_route(title):
route = "#app.route(/%s)" %(title)
def welcome():
return render_template("%s.html" %(title))
with open('test1.txt', 'w') as f:
f.write('%r\n%r\n' % (route, welcome))
return welcome
make_route('Hi')
I would use philhag answer but use %s instead of %r or you'll write a string, and you could use .name if you want to use the function more than once(Which you probably do).
def make_route(title):
route = "#app.route('/%s')" %(title)
def welcome():
return render_template("%s.html" %(title))
with open('test2.py', 'w') as f:
f.write('%s\n%s\n' % (route, welcome))
welcome.__name__ = title
return welcome
make_route('Hi')

Reading From File and Miming a Database

Here's what I am trying to do:
I've built a mini-system that allows for user registering & so on, but the system is very dependent on db_parse() and user_exists(), because that are the main two conditionals for the whole script to run.
Basically I am testing if an user exists with user_exists('username') which should return a "True" (It's a dict which has a value of either True/False).
So, here's the whole code to it (Please excuse the indendation:
class __system():
def __init__(self):
self.usernames = []
self.passwords = []
self.dbname = 'database.txt'
self.privilege = [1,2,3]
self.backupdb = 'backup.txt'
def db_parse(self):
d = {'username':[],
'uid':[],
'password':[],
'pwdid':[]
}
with open(self.dbname,'r') as f:
lines = ([line.rstrip() for line in f])
f.flush()
for x in xrange(0,len(lines)):
if x%2==0:
d['username'].append(lines[x])
d['uid'].append(x) #-> number of line in the file
if x%2==1:
d['password'].append(lines[x])
d['pwdid'].append(x)
print lines
f.close()
return d
def user_exists(self, username=''):
d = {'exists': None,
'uid': None
}
db = self.db_parse()
ylen = len(db['username'])
for y in range(0,ylen):
if username == db['username'][y]:
d['exists'] = True
d['uid'] = db['uid'][y]
else:
d['exists'] = False
d['uid'] = None
return d
def main():
obj = __system()
print obj.user_exists('user1')
if __name__ == "__main__":
main()
The 'database.txt' is looking like this:
user1<br>
203ad5ffa1d7c650ad681fdff3965cd2<br>
user2<br>
6e809cbda0732ac4845916a59016f954<br>
How can I say this...this sometimes work, this doesn't and I've done debugging for 10 hours straight (Yea, that's right.)
I can't seem to catch why it returns "False" and "uid:0" when the user clearly exists and then, 5 minutes later, only re-pasting the code, it does work.
You're going to kick yourself for this, but the issue is here:
for y in range(0,ylen):
if username == db['username'][y]:
d['exists'] = True
d['uid'] = db['uid'][y]
else:
d['exists'] = False
d['uid'] = None
return d
If username matches the first user in the file, your for loop continues on to the second user in the file, which, of course, won't match. So it ends up returning False/None. You just need to add a break if a match is found:
for y in range(0,ylen):
if username == db['username'][y]:
d['exists'] = True
d['uid'] = db['uid'][y]
break # Add this
else:
d['exists'] = False
d['uid'] = None
return d
As an aside, you don't need to call f.close() if you're opening the file using with open(...) as f. The file will automatically close when you leave the with block. You should also use for x, line in enumerate(lines): instead of for x in xrange(0, len(lines)):

Python Skipping 'for' loop

I'm making a program that searches a file for code snippets. However, in my search procedure, it skips the for loop entirely (inside the search_file procedure). I have looked through my code and have been unable to find a reason. Python seems to just skip all of the code inside the for loop.
import linecache
def load_file(name,mode,dest):
try:
f = open(name,mode)
except IOError:
pass
else:
dest = open(name,mode)
def search_file(f,title,keyword,dest):
found_dots = False
dest.append("")
dest.append("")
dest.append("")
print "hi"
for line in f:
print line
if line == "..":
if found_dots:
print "Done!"
found_dots = False
else:
print "Found dots!"
found_dots = True
elif found_dots:
if line[0:5] == "title=" and line [6:] == title:
dest[0] = line[6:]
elif line[0:5] == "keywd=" and line [6:] == keyword:
dest[1] = line[6:]
else:
dest[2] += line
f = ""
load_file("snippets.txt",'r',f)
search = []
search_file(f,"Open File","file",search)
print search
In Python, arguments are not passed by reference. That is, if you pass in an argument and the function changes that argument (not to be confused with data of that argument), the variable passed in will not be changed.
You're giving load_file an empty string, and that argument is referenced within the function as dest. You do assign dest, but that just assigns the local variable; it does not change f. If you want load_file to return something, you'll have to explicitly return it.
Since f was never changed from an empty string, an empty string is passed to search_file. Looping over a string will loop over the characters, but there are no characters in an empty string, so it does not execute the body of the loop.
Inside each function add global f then f would be treated as a global variable. You don't have to pass f into the functions either.

Compare two text files and return the difference (case insensitive)

I'm new to Python programming so forgive me if my code is not efficient, etc. I need to compare text file B with text file B and print the results out to another file. Simply put, result C = text file A - text file B.
I have the following code which works, however, there are duplicate results due to upper and lower cases. How can I make it such that my program can compare it without case sensitivity?
#!/usr/local/bin/python -u
file1='A_GAGL.txt'
file2='B_GGL.txt'
def key(line):
return tuple(line.strip().split()[0:2])
def make_key_set(file_path):
return set(key(line) for line in open(file_path))
def filtered_lines(file_path1, file_path2):
key_set = make_key_set(file_path2)
return (line for line in open(file_path1) if key(line) not in key_set)
if __name__ == "__main__":
file3 = open("file4.txt", "w")
for line in filtered_lines(file1, file2):
file3.write(line)
file3.close()
Many thanks in advance
In make_key_set, convert everything to lowercase:
return set(key(line.lower()) for line in open(file_path)
Then in filtered_lines check whether the lowercase line is in key_set (but return the original-case line):
return (line for line in open(file_path1) if key(line.lower()) not in key_set)
You could make your keys uppercase:
def key(line):
return map(str.upper, line.strip().split()[0:2])
Also, instead of file3 = open("file4.txt", "w") and file3.close(),
if you Python version is 2.5 or newer, the better way is to use a with context manager:
with open("file4.txt", "w") as file3:
for line in filtered_lines(file1, file2):
file3.write(line)
This guarantees the file is closed no matter how it exits the with-block, and it ensures you never forget to call close().
if your files are line-oriented plain text, then:
class HashableDictWrapper(object):
def __init__(self, s):
self.original_str = s
self._hash_key = hash(s.strip()[0:2].lower())
def __hash__(self):
return self._hash_key
def __eq__(self, other):
return self.__hash__()==other.__hash__()
if __name__=="__main__":
a = map(HashableDictWrapper, open("A.txt"))
b = map(HashableDictWrapper, open("B.txt"))
result = map(lambda x:x.original_str, set(a) - set(b))
open("C.txt", "w").writelines(result)

Python: Problem with if statement

I have problem with a if statement code below:
do_blast(x):
test_empty = open('/home/rv/ncbi-blast-2.2.23+/db/job_ID/%s.blast' % (z), 'r')
if test_empty.read() == '':
test_empty.close()
return 'FAIL_NO_RESULTS'
else:
do_something
def return_blast(job_ID):
if job_ID == 'FAIL_NO_RESULTS':
return '<p>Sorry no results :( boooo</p>'
else:
return open('/home/rv/ncbi-blast-2.2.23+/db/job_ID/job_ID_%s.fasta' % (job_ID), 'r').read()
For some reason the code tries to assign "job_ID" to the fasta file in return_blast even though it should have returned "sorry no results". I also understand the file names and extensions are different i have my reasons for doing this.
The code works perfectly when the test_empty file is not empty.
I'm not sure if this is the problem, but your code isn't indented correctly (and that matters in Python). I believe this is what you were wanting:
do_blast(x):
test_empty = open('/home/rv/ncbi-blast-2.2.23+/db/job_ID/%s.blast' % (z), 'r')
if test_empty.read() == '':
test_empty.close()
return 'FAIL_NO_RESULTS'
else:
do_something
def return_blast(job_ID):
if job_ID == 'FAIL_NO_RESULTS':
return '<p>Sorry no results :( boooo</p>'
else:
return open('/home/rv/ncbi-blast-2.2.23+/db/job_ID/job_ID_%s.fasta' % (job_ID), 'r').read()
I don't think your code would have even run though..
Maybe some simple printf style debugging will help:
def return_blast(job_ID):
print 'job_ID: ', job_ID
# ...
Then you can at least see what "job_ID" your function receives. This is crucial for trying to figure out why your if statement fails.

Categories