Exceptions and Output - python

I have problem when calling my function, I am receiving bad output as I will explain later in the text.
These are the resources I am working with:
Main_Building=[10,12,14,17,21,25,30,36,43,52,62,74,89,107,128,154,185,222,266,319,383,460,552,662,795,954,1145,1374,1648,1978]
Barracks=[16,19,23,28,33,40,48,57,69,83,99,119,143,171,205,247,296,355,426,511,613,736,883,1060,1272]
Stables=[20,24,29,35,41,50,60,72,86,103,124,149,178,214,257,308,370,444,532,639]
Workshop=[24,29,35,41,50,60,72,86,103,124,149,178,214,257,308]
Blacksmith=[19,23,27,33,39,47,57,68,82,98,118,141,169,203,244,293,351,422,506,607]
Market=[10,12,14,17,21,25,30,36,43,52,62,74,89,107,128,154,185,222,266,319,383,460,552,662,795]
Axe=[6,7,9,10,12,15,18,21,26,31,37,45,53,64,77,92,111,133,160,192,230,276,331,397,477,572,687,824,989,1187]
Clay_Pit=[6,7,9,10,12,15,18,21,26,31,37,45,53,64,77,92,111,133,160,192,230,276,331,397,477,572,687,824,989,1187]
Mine=[6,7,9,10,12,15,18,21,26,31,37,45,53,64,77,92,111,133,160,192,230,276,331,397,477,572,687,824,989,1187]
Settler_House=[5,6,7,9,10,12,15,18,21,26,31,37,45,53,64,77,92,111,133,160,192,230,276,331,397,477,572,687,824,989]
Warehouse=[6,7,9,10,12,15,18,21,26,31,37,45,53,64,77,92,111,133,160,192,230,276,331,397,477,572,687,824,989,1187]
Wall=[8,10,12,14,17,20,24,29,34,41,50,59,71,86,103,123,148,177,213,256]
Here is my code:
def buildings(points):
for i in range(0,30):
try:
if Main_Building[i]>=points:
del Main_Building[i:]
if Barracks[i]>=points:
del Barracks[i:]
if Stables[i]>=points:
del Stables[i:]
if Workshop[i]>=points:
del Workshop[i:]
if Blacksmith[i]>=points:
del Blacksmith[i:]
if Market[i]>=points:
del Market[i:]
if Axe[i]>=points:
del Axe[i:]
if Clay_Pit[i]>=points:
del Clay_Pit[i:]
if Mine[i]>=points:
del Mine[i:]
if Settler_House[i]>=points:
del Settler_House[i:]
if Warehouse[i]>=points:
del Warehouse[i:]
if Wall[i]>=points:
del Wall[i:]
except IndexError:
continue
The problem is when the it comes to Condition of Blacksmith, it looks to me as the condition is only passed, and the same for others continuing to Wall condition. The condition is determining where to stop and delete rest of the list for further use. The lists are different lengths so I used simple exception for when it is out of range it just skips and continue to next condition.
Suggested output when def buildings(100):
Blacksmith=[19,23,27,33,39,47,57,68,82,98]
Actual output is whole list without any change. The same applies to continuing condition.
What I tried:
I tried to restart Python but that unfortunately was not it.
If I misspelled the variable name.
Redoing spacing on every condition.
Maybe solution but not effective, adding to each condition try exception ?(Not a good Idea in my opinion).
Why it skips the conditions ?
Thank you for your help and time.

Continue will return to the beginning of current loop and grab next index. This means that if an error occurred halfway, the last half is skipped. It was also quite lengthy. Here is my solution.
data = [Main_Building, Barracks, Stables, Workshop, Blacksmith, Market, Axe, Clay_Pit, Mine, Settler_House, Warehouse, Wall]
def buildings(points):
for building in data: # loop through each building seperately, shortens code and removes arbitrary loop number
for point in building: # loop through each buildings index, same as your code
if point >= points:
del building[building.index(point):]
buildings(20)
print data

If any error occured between try-except, Python will pass or continue all of the codes between try-except.
try:
a = int(input("integer: "))
print("print this")
print("print that")
except:
pass
Output:
>>>
integer: ab
>>>
See that print this and print that not printed. You should catch the errors one by one.
try:
a = int(input("integer: "))
except:
pass
print("print this")
print("print that")
>>>
integer: ab
print this
print that
>>>

Related

Check if a condition is respect instantly

I have a complex project and I will try to simplify one of the main problem of the project. So there is the simplification:
We can Imagine a while loop like this:
while(condition):
statement1
statement2
statement3
...
statementn
In this loop there n statements, and each statement can be whatever(function, loop, if statement,...) and there is a condition in the loop, this condition i want to check it BEFORE the while loop do it. Because if the condition is respect since the first statement I have to wait until the end of the while to check if the condition is respect... So there is my question is possible to check the condition BEFORE the loop without have a check-function between EACH statements of the whileloop ?
Because in fact, it's work... BUT the code isn't clear, I really think this way we pollute my code and i want to work more efficiently and with a beautiful code, so how can I solve my problem without this constraint ?
PS: I think about event listener like javascript but i found poor information about them on python, but if there is a tool which act like event listener it would be great !
It sounds like you want to clean up all your if-then-break statements into a single function that handles the "checking" of the value of a. For that purpose you could use exceptions:
import random
class ItIsFiveException(Exception): pass
def check(a):
if a == 5:
raise ItIsFiveException
try:
a = 0
while(a != 5):
a = random.randint(1,5); check(a)
a = random.randint(1,5); check(a)
a = random.randint(1,5); check(a)
a = random.randint(1,5); check(a)
except ItIsFiveException:
print("I saw a five!")
You just have to define your own python Exception as a class, and the raise it in your manually-defined check(a) function. Then you can wrap your entire while loop in a try-except block and catch your exception.
I am not sure if I understand you right, but this is what I'd do:
flag = False
while not flag:
for i in range(4):
a = random.randint(1, 5)
if a == 4:
flag = True
break
I don't know exactly what it happens with "a" but if if you can chain the conditions and will stop when the first one fails
while(checkRandom()):
...
def checkRandom(a):
return random.randint(1,5) == 5 and random.randint(1,5)....
If you can loop the generation of random values you can use
while(a!=5):
for item in range(1, 5):
a=random.randint(1,5)
if a==5:
break

Print else only once? [duplicate]

This question already has answers here:
Print out message only once from the for loop
(4 answers)
Closed 5 years ago.
how do I get my else print to only print once instead of for every row that the string doesn't exist? I tried moving it around by tabbing back a couple of layers but it doesn't work. I understand the logic, I but don't know how to limit it. I'm adding a little bit at a time to my parsing scripts for practice, learning as I go, but this one got me. Thanks!
import csv
# Testing finding something specifical in a CSV, with and else
testpath = 'C:\Users\Devin\Downloads\users.csv'
developer = "devin"
with open (testpath, 'r') as testf:
testr = csv.reader(testf)
for row in testr:
for field in row:
if developer in row:
print row
else:
print developer + " does not exist!"
In Python, you can have an else clause attached to your for loop. For example
>>> for i in range(10):
... if i == 5: break # this causes the else statement to be skipped
... else:
... print 'not found'
...
Note 5 was found so the else statement is not executed
>>> for i in range(10):
... if i == 15: break
... else:
... print 'not found'
...
not found
See the documentation on for statements
A break statement executed in the first suite terminates the loop
without executing the else clause’s suite. A continue statement
executed in the first suite skips the rest of the suite and continues
with the next item, or with the else clause if there is no next item.
See Gibson's answer first. You can do this:
for row in testr:
found = False
for field in row:
if developer in row:
print row
found = True
break
if found: break
else:
print developer + " does not exist!"
You can also omit the found flag (as suggested by Jean-François Fabre in the comment) but this makes a bit hard to understand imo (I had to compile in my head):
for row in testr:
for field in row:
if developer in row:
print row
# We found the developer. break from the inner loop.
break
else:
# This means, the inner loop ran fully, developer was not found.
# But, we have other rows; we need to find more.
continue
# This means, the else part of the inner loop did not execute.
# And that indicates, developer was found. break from the outer loop.
break
else:
# The outer loop ran fully and was not broken
# This means, developer was not found.
print developer, "does not exist!"

List Comprehension python?

I have a function like this:
for product in responseSoup.findAll("offersummary"):
try:
if product.lowestnewprice.formattedprice != None:
price.append(product.lowestnewprice.formattedprice.text)
else:
price.append("")
except:
price.append("")
I am confused how to do the if/else statement with the try/except block? Will list comprehension speed up efficiency?
[product.lowestnewprice.formattedprice for product in responseSoup.findAll("offersummary")]
Here is a very readable solution:
prices = []
for product in responseSoup.findAll("offersummary"):
price = product.get(lowestnewprice, {}).get(formattedprice, {}).get(text)
if price is not None:
prices.append(price)
else:
prices.append('')
If you really don't care about readability, here's a very atrocious looking one-liner:
price = [''
if product.get(lowestnewprice, {}).get(formattedprice, {}).get(
text) is None else
product.lowestnewprice.formattedprice.text
for product in responseSoup.findAll("offersummary")]
They do essentially the same thing, but, in my opinion, the more readable solution is better.
EDIT
I just figured out a much better one-liner:
price = [product.get(lowestnewprice,{}).get(formattedprice,{}).get(text) or ''
for product in responseSoup.findAll("offersummary")]
It's still less readable than the "very readable" solution, but it is not too bad. Now the decision really comes down to a matter of your preference.
try and except blocks are used to see if the following code works. If not and it matches the given error, run that block of code. Else, run the other line of code. For example:
try:
m = raw_input("Please enter an integer")
n = int(m)
except ValueError:
print "Invalid number"
else:
print n
So, the program attempts to assign m the input from the user. Then n is assigned the input as an integer. Now the error chosen is ValueError since if m is a string, the conversion to n will raise that error. If it does, then it does the code in the except block, which is to print "Invalid number". If the conversion is successful, then print n.
Now with your program, you will try the if and else block. If the code doesn't work and it raises the error given in the except block, it will do price.append(""). Else, it will run the code in the else block, which you don't have. You need the else: to work in your try/except block for it to work including a specified error after the keyword except in your except statement.

Python 3.x - Input only returns first item

I have been having problems with a block of code in a little project and I can't seem to fix it.
In the below code, I define inputrace() so that a process is carried out where the player types in a number that is above 0 and below 13 (there are 12 choices, each dictated by a number); it also checks for blank lines and strings and has the program state that there is an error and ask for user input again if they are detected. If it passes the check, RaceInp is returned and set to RaceChoice which allows the code below it to assign a Race to the player based on their selection.
#race check
def inputrace():
print ("Input number")
RaceInp = input()
Check = RaceInp
try:
int(RaceInp)
except ValueError:
print("Numbers only!")
inputrace()
if not int(Check)>12 or int(Check)<1:
return RaceInp
print (RaceInp) #this is here so I can check the value returned
Race = "NA"
RaceChoice = inputrace()
print (RaceChoice)
#assign race
if RaceChoice == "1":
Race = "Human"
#continues down to twelve
Everything works when valid strings are put in (any number 1-12), but things break when I purposefully put in an invalid string. It seems like RaceInp only retains the first user input and does not change, even after the function is recalled from an error. That means if I were to put in "a," the program will tell me it is wrong and ask again. However, when I put in "1" in an attempt to correct it, it accepts it but still keeps RaceInp as "a."
Is there any fix to this? I have no clue what's going on.
I appreciate the help and sorry if I got anything wrong in the question!
It seems that the problem is that you put the inputrace in a recursion instead of a loop. Something like this would probably be better:
def input_race():
while True:
print("Input a number between 1 and 12.")
race_input = input()
try:
race_input = int(race_input)
if race_input >= 1 and race_input <= 12:
return race_input
except ValueError:
pass
print ("'{input}' is not a number.".format(input=race_input))
race = "NA"
race_choice = input_race()
if race_choice == 1:
race = "Human"
print(race)

Can't get my loop & match to append to correct list

I´m experiencing problems with my code.
I can´t get it to append to the list not_found as well as it loops twice for some reason.
Can anyone point me in the right direction? The match works for my_track, but it doesn't when it doesn't match.
# coding: utf-8
#!/usr/bin/env python
import spotimeta
import sys
import time
my_tracks = raw_input("Please enter a sentence: ").title().split()
playlist = []
real_playlist = []
not_found = []
def check_track(track_name, my_track, track_href):
if track_name == my_track:
playlist.append(track_href)
return 1
# make sure the user does not input a single word as input
if (len(my_tracks) > 1):
path = my_tracks[1]
else:
sys.exit("Invalid input, please enter a sentence.")
# let's search
for my_track in my_tracks:
match = 0
print "Searching for '%s'\n" % (my_track),
data = spotimeta.search_track(my_track)
for result in data['result']:
if not match == 1:
try:
match = check_track(result["name"],my_track,result["href"])
except Exception, e:
error = "not available"
else:
if data['total_results'] > 0:
not_found.append(my_track)
You should try debugging it. One of the simplest ways of debugging is add the lines:
import pdb
pdb.set_trace()
Then when you run the script it will stop at the set_trace line in the debugger.
Check out http://docs.python.org/library/pdb.html for more information.
From my understanding you're trying to do something like:
for my_track in my_tracks:
print "Searching for '%s'\n" % (my_track),
data = spotimeta.search_track(my_track)
for result in data['result']:
if result['name'] == my_track:
playlist.append(result['href'])
elif data['total_results'] > 0:
not_found.append(my_track)
Will this more or less work for you?
Please help me to understand.
Right off the bat, I'm noticing two things.
First, you're checking data['total_results'] a bit late; if the total results value is greater than zero (wait, what?), then you want to add it to the list immediately and move on without parsing the data. I would, after the call from spotimeta.search_track(), check to see if this is the data you don't want (then subsequently add it into the list).
Second, I'm confused about the intention of your for loop. If you're going through it to only find one item, then you can use the in statement (my_track in result).

Categories

Resources