Python: Problem with if statement - python

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.

Related

How can I increase code readability in python for this?

I am running my script in Flask and to catch and print the errors on the server I have made functions that either return None if succeeded else return an error message.
The problem is I have many functions which runs one after another and uses global variable from earlier function, this makes the code unorganized. What can I do?
App.py
from flask import Flask
from main import *
app = Flask(__name__)
#app.route('/')
def main():
input = request.args.get('input')
first_response = function1(input)
if first_response is None:
second_response = function2() # no input from hereon
if second_response is None:
third_response = function3() # functions are imported from main.py
if third_response is None:
...
if ...
else ...
else:
return third_response
else:
return second_response
else:
return first_response
main.py
def function1(input):
global new_variable1
if input is valid:
new_variable1 = round(input,2)
else:
return "the value is not integer"
def function2():
global new_variable2
if new_variable1 > 8:
new_variable2 = new_variable1 / 8
else:
return "the division is not working, value is 0"
def function3():
...
This is just a demo of what's going on. The last function will return a value either side. So if everything goes right I would be able to see the right output as well as I will see error on any given function.
The code works fine, but I need better alternative to do this.
Thanks!
Ah...you have (correctly) determined that you have two things to do:
Process your data, and
Deal with errors.
So let's process the data replacing global with parameteters (and come back to the error handling in a bit). You want to do something like this.
main.py
def function1(some_number):
if some_number is valid:
return round(some_number, 2)
def function2(a_rounded_number):
if a_rounded_number > 8:
return a_rounded_number / 8
So each function should return the results of its work. Then the calling routine can just send the results of each function to the next function, like this:
app.py
# [code snipped]
result1 = function1(the_input_value)
result2 = function2(result1)
result3 = function3(result2)
But...how do we deal with unexpected or error conditions? We use exceptions, like this:
main.py
def function1(some_number):
if some_number is valid:
return round(some_number, 2)
else:
raise ValueError("some_number was not valid")
and then in the calling routine
app.py
try:
result1 = function1(some_input_value)
except (ValueError as some_exception):
return str(some_exception)

Python IndentionError driving me crazy [duplicate]

The runtime keeps telling me:
expected an indented block
But I don't want write nothing inside my except block, I just want it to catch and swallow the exception.
Just write
pass
as in
try:
# Do something illegal.
...
except:
# Pretend nothing happened.
pass
EDIT: #swillden brings up a good point, viz., this is a terrible idea in general. You should, at the least, say
except TypeError, DivideByZeroError:
or whatever kinds of errors you want to handle. Otherwise you can mask bigger problems.
For those who are very unclear as to why you would want to do this. Here is an example where I initially thought that an empty block would be a good idea:
def set_debug_dir(self, debug_dir=None):
if debug_dir is None:
debug_dir = self.__debug_dir
elif isinstance(debug_dir, (Path, str)):
debug_dir = debug_dir # this is my null operation
elif isinstance(debug_dir, list):
debug_dir = functools.reduce(os.path.join, debug_dir)
else:
raise TypeError('Unexpected type for debug_dir: {}'.format(type(debug_dir).__name__))
But it would be more clear to reorganize the statement:
def set_debug_dir(self, debug_dir=None):
if debug_dir is None:
debug_dir = self.__debug_dir
elif isinstance(debug_dir, list):
debug_dir = functools.reduce(os.path.join, debug_dir)
elif not isinstance(debug_dir, (Path, str)):
raise TypeError('Unexpected type for debug_dir: {}'.format(type(debug_dir).__name__))
I've never done this in more permanent code, but I frequently do it as a placeholder
if some_expression:
True
else:
do_something(blah)
Just sticking a True in there will stop the error. Not sure if there's anything bad about this.

Multiple Try/Except for Validate Config-File

Thats my first question on Stackoverflow and im a totally Python beginner.
I want to write, to get firm with python, a small Backup-Programm, the main part is done, but now i want to make it a bit "portable" and use a Config file, which i want to Validate.
My class "getBackupOptions" should be give Back a validate dict which should be enriched with "GlobalOptions" and "BackupOption" so that i finally get an fully "BackupOption" dict when i call "getBackupOptions.BackupOptions".
My Question now is, (in this Example is it easy, because its only the Function which check if the Path should be Recursive searched or not) how to simplify my Code?
For each (possible) Error i must write a new "TryExcept" Block - Can i Simplify it?
Maybe is there another way to Validate Config Files/Arrays?
class getBackupOptions:
def __init__(self,BackupOption,GlobalOptions):
self.BackupOption = BackupOption
self.GlobalOptions = GlobalOptions
self.getRecusive()
def getRecusive(self):
try:
if self.BackupOption['recursive'] != None:
pass
else:
raise KeyError
except KeyError:
try:
if self.GlobalOptions['recursive'] != None:
self.BackupOption['recursive'] = self.GlobalOptions['recursive']
else:
raise KeyError
except KeyError:
print('Recusive in: ' + str(self.BackupOption) + ' and Global is not set!')
exit()
Actually i only catch an KeyError, but what if the the Key is there but there is something else than "True" or "False"?
Thanks a lot for you help!
You may try this
class getBackupOptions:
def __init__(self,BackupOption,GlobalOptions):
self.BackupOption = BackupOption
self.GlobalOptions = GlobalOptions
self.getRecusive()
def getRecusive(self):
if self.BackupOption.get('recursive') == 'True' and self.GlobalOptions.get('recursive') == 'True':
self.BackupOption['recursive'] = self.GlobalOptions['recursive']
else:
print('Recusive in: ' + str(self.BackupOption) + ' and Global is not set!')
exit()
Here get method is used, therefore KeyError will not be faced.
If any text other than True comes in the field it will be considered as False.

Python File Functions

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+':'

Greedy execution of statements?

I have something like this using BeautifulSoup:
for line in lines:
code = l.find('span', {'class':'boldHeader'}).text
coded = l.find('div', {'class':'Description'}).text
definition = l.find('ul', {'class':'definitions'}).text
print code, coded, def
However, not all elements exist at all times. I can enclose this in a try except so that it does not break the program execution like this:
for line in lines:
try:
code = l.find('span', {'class':'boldHeader'}).text
coded = l.find('div', {'class':'Description'}).text
definition = l.find('ul', {'class':'definitions'}).text
print code, coded, def
except:
pass
But how I execute the statements in a greedy fashion? For instance, if there are only two elements available code and coded, I just want to get those and continue with the execution. As of now, even if code and coded exist, if def does not exist, the print command is never executed.
One way of doing this is to put a try...except for every statement like this:
for line in lines:
try:
code = l.find('span', {'class':'boldHeader'}).text
except:
pass
try:
coded = l.find('div', {'class':'Description'}).text
except:
pass
try:
definition = l.find('ul', {'class':'definitions'}).text
except:
pass
print code, coded, def
But this is an ugly approach and I want something cleaner. Any suggestions?
How about capture the "ugly" code in a function, and just call the function as needed:
def get_txt(l,tag,classname):
try:
txt=l.find(tag, {'class':classname}).text
except AttributeError:
txt=None
return txt
for line in lines:
code = get_txt(l,'span','boldHeader')
coded = get_txt(l,'div','Description')
defn = get_txt(l,'ul','definitions')
print code, coded, defn
PS. I changed def to defn because def is a Python keyword. Using it as a variable name raises a SyntaxError.
PPS. It's not a good practice to use bare exceptions:
try:
....
except:
...
because it almost always captures more that you intend. Much better to be explicit about what you want to catch:
try:
...
except AttributeError as err:
...
First of all, you can test for None instead of catching an exception. l.find should return None if it doesn't find your item. Exceptions should be reserved for errors and really extraordinary situations.
Second thing you can do is to create an array of all HTML elements you want to check and then have a nested for loop. Since it's been a while since I've used python, I will outline the code and then (hopefully) edit the answer when I test it.
Something like:
elementsToCheck = [
[ 'span', {'class':'boldHeader'} ],
[ 'div', {'class':'Description'} ],
[ 'ul', {'class':'definitions'} ]]
concatenated = ''
for line in lines:
for something in elementsToCheck
element = l.find(something[0], something[1])
if element is not None
concatenated += element.text
print concatenated
Obviously the code above won't work, but you should get the idea. :)

Categories