while loop == 6:
if EVENTCOUNT >= 4:
_, username, para, value = event.split(" ", 3)
try:
self.dbcur.execute('select ? from users where name = ?', [para, username])
if rrf is None:
print notex
else:
print str(username)+" has been altered: "+str(para)+" => "+str(value)+"."
while loop == 2:
again = raw_input("Is that all? (Y/N)")
while True:
if again == "Y":
# edit another parameter
loop=4
elif again == "N":
print "Thanks! Bye! \nAll credits of this program go to Trey."
#end program
break
else:
print "Sorry! That wasn't Y or N."
loop == 2
I get an the error: "IndentationError: expected an indented block" and there is an error underneath the if EVENTCOUNT >=4:
Use an IDE, which often has an indentation tool for automatically converting mixed tabs and spaces to either all tabs or spaces. Here is your code with 4 spaces per indent.
while loop == 6:
if EVENTCOUNT >= 4:
_, username, para, value = event.split(" ", 3)
try:
self.dbcur.execute('select ? from users where name = ?', [para, username])
if rrf is None:
print notex
else:
print str(username)+" has been altered: "+str(para)+" => "+str(value)+"."
while loop == 2:
again = raw_input("Is that all? (Y/N)")
while True:
if again == "Y":
# edit another parameter
loop=4
elif again == "N":
print "Thanks! Bye! \nAll credits of this program go to Trey."
#end program
break
else:
print "Sorry! That wasn't Y or N."
loop == 2
except Exception,err:
print "error"
You must use a consistent indentation for all blocks within a file - I (and PEP8) strongly recommend four spaces.
Mixing tabs and spaces in a single file is bad because tabs have variable perceived widths based on the developer's environment. Mixing the number of spaces within a single file can confuse the interpreter.
Related
I'm trying to run the program in the following article:
https://blockgeeks.com/guides/python-blockchain-2/
I've copied all of the code into my Spyder IDE. When i run it there's a while loop which starts up asking the user to choose a number from the list of options it prints.
After selecting a number the program should perform the requested action. When i select it though it just loops back to the start of the while loop.
It appears to be ignoring the rest of the code in the while loop (the if statement part).
Confusingly if i take the parts of the code from the program which are used in the while loop and run them separately they work i.e if i run the below code and select the number 1 for my choice it will run the code in the if statement.
Why would the if statement run here but not in the main program?
#function 1:
def get_user_choice():
user_input = input("enter a number: ")
return user_input
#function 2:
def get_transaction_value():
tx_recipient = input('Enter the recipient of the transaction: ')
tx_amount = float(input('Enter your transaction amount '))
return tx_recipient, tx_amount
while True:
print("Choose an option")
print('Choose 1 for adding a new transaction')
print('Choose 2 for mining a new block')
print('Choose 3 for printing the blockchain')
print('Choose anything else if you want to quit')
user_choice = get_user_choice()
if user_choice == '1':
tx_data = get_transaction_value()
print(tx_data)
Update:
Sorry i realise i may not have been very clear what the problem is.
The above code is part of the code from the entire program and runs as expected in isolation from the main program.
The below code is the entire program from the article in the link. It includes all of the code in the program. If i run this main program the while loop doesn't use the if statement. It appears to just be breaking straight out of the loop after i select 1, 2 or 3 (any other number should break out of the loop anyway).
Here's a link for a screen shot showing what the console looks like after i have selected the number 1 for the option.
https://ibb.co/RNy2r0m
# Section 1
import hashlib
import json
reward = 10.0
genesis_block = {
'previous_hash': '',
'index': 0,
'transaction': [],
'nonce': 23
}
blockchain = [genesis_block]
open_transactions = []
owner = 'Blockgeeks'
def hash_block(block):
return hashlib.sha256(json.dumps(block).encode()).hexdigest()
# Section 2
def valid_proof(transactions, last_hash, nonce):
guess = (str(transactions) + str(last_hash) + str(nonce)).encode()
guess_hash = hashlib.sha256(guess).hexdigest()
print(guess_hash)
return guess_hash[0:2] == '00'
def pow():
last_block = blockchain[-1]
last_hash = hash_block(last_block)
nonce = 0
while not valid_proof(open_transactions, last_hash, nonce):
nonce += 1
return nonce
# Section 3
def get_last_value():
""" extracting the last element of the blockchain list """
return(blockchain[-1])
def add_value(recipient, sender=owner, amount=1.0):
transaction = {'sender': sender,
'recipient': recipient,
'amount': amount}
open_transactions.append(transaction)
# Section 4
def mine_block():
last_block = blockchain[-1]
hashed_block = hash_block(last_block)
nonce = pow()
reward_transaction = {
'sender': 'MINING',
'recipient': owner,
'amount': reward
}
open_transactions.append(reward_transaction)
block = {
'previous_hash': hashed_block,
'index': len(blockchain),
'transaction': open_transactions,
'nonce': nonce
}
blockchain.append(block)
# Section 5
def get_transaction_value():
tx_recipient = input('Enter the recipient of the transaction: ')
tx_amount = float(input('Enter your transaction amount '))
return tx_recipient, tx_amount
def get_user_choice():
user_input = input("Please give your choice here: ")
return user_input
# Section 6
def print_block():
for block in blockchain:
print("Here is your block")
print(block)
# Section 7
while True:
print("Choose an option")
print('Choose 1 for adding a new transaction')
print('Choose 2 for mining a new block')
print('Choose 3 for printing the blockchain')
print('Choose anything else if you want to quit')
user_choice = get_user_choice()
if user_choice == 1:
tx_data = get_transaction_value()
recipient, amount = tx_data
add_value(recipient, amount=amount)
print(open_transactions)
elif user_choice == 2:
mine_block()
elif user_choice == 3:
print_block()
else:
break
[1]: https://i.stack.imgur.com/FIrn7.png
When comparing values, Python takes a stronger route regarding data types than some other languages. That means no string in Python will equal a number.
Or in other terms "1" == 1 will be False.
That means you have to consider that in Python 3 you will receive a string from input() (not necessarily so in Python 2).
You can either compare this directly to another string:
user_choice = input()
if user_choice == "1":
print("You chose item 1")
Or you can convert it into a number first and compare it to a number:
user_choice = int(input())
if user_choice == 1:
print("You chose item 1")
Note that in the former case it might not be robust if the user enters extra spaces and in the latter case it will fail very loudly with an exception if the user doesn't enter an integer (or even nothing at all).
Both ways can be handled with extra code if necessary. In the former case, you can strip whitespace with user_input = input().strip() and in the latter case you can catch the exception with a try ... except ... block.
You have only handled the case for user_choice == '1'. If you enter anything other than 1, the program will return control to the beginning of the while loop.
I'll suggest you use a debugger to see what user_choice is before the if condition. If not, just use prints.
print("user_choice: {}, type: {}".format(user_choice, type(user_choice))
This question already has answers here:
How to break out of while loop in Python?
(5 answers)
Closed 4 years ago.
I'm trying to use a while loop to iterate through a function in Python which requests a user input, i.e. commitchanges to perform one of two actions, and if the input is not valid after a few attempts to close the program.
If the input is equal to 'y' (Yes) then the program should commit the changes made by the SQL update query, i.e. conn.commit()
If the input is equal to 'n' (No) then the program should not commit the changes and rollback, i.e. conn.rollback()
If the input is anything other than 'y' or 'n' then the program should alert the user that that is not a valid input.
Here's my current function:
def action(inputattempts):
commitchanges = input()
if commitchanges.lower() == 'y':
try:
conn.commit()
print ('Table Updated. No. of records updated:', totalupdates)
except cx_Oracle.DatabaseError as error:
print(error)
elif commitchanges.lower() == 'n':
conn.rollback()
print ('Rollback - No updates made to table')
else:
print ('Not a valid selection - Try again')
print (inputattempts)
Where the variable totalupdates is a global variable defined later on in the program which counts the number of records affected by the curs.execute SQL query.
I'm then calling the above function in a while loop as follows:
inputattempts = 0
while (inputattempts < 4):
inputattempts += 1
action(inputattempts)
print ('FAILED')
Essentially, I'd like the user to have a maximum of 4 attempts at entering a valid input, i.e. 'y' or 'n' before the program aborts if the input is not valid after those attempts. However, if 'y' or 'n' is entered the first time the function is called the program should either commit or rollback and exit the loop.
Currently, I'm having to complete 4 iterations of the while loop regardless of my input. Is there a way I can tweak any of that syntax to exit the loop when the above conditions are met?
As suggested by #rdimaio:
Your action function returns True if the flow was valid; False otherwise (i.e. invalid user input).
def action(inputattempts):
commitchanges = input()
if commitchanges.lower() == 'y':
try:
conn.commit()
print ('Table Updated. No. of records updated:', totalupdates)
except cx_Oracle.DatabaseError as error:
print(error)
return True
elif commitchanges.lower() == 'n':
conn.rollback()
print ('Rollback - No updates made to table')
return True
print ('Not a valid selection - Try again')
print (inputattempts)
return False
Then, you check whether the flow was valid in your while and break when condition is met:
input_attempts = 0
while input_attempts < 4:
input_attempts += 1
if action(input_attempts):
break
if input_attempts == 4:
print ('FAILED')
Just get the user input outside of actions() and pass it as a parameter:
while inputattempts < 4:
inputattempts += 1
commit_changes = input()
action(inputattempts, commit_changes)
Then after the call to action() you can condition on what you need and break out if appropriate.
You can return a value from your function and check over it's returned value to break or not.
def action(inputattempts):
correct_input = True
commitchanges = input()
if commitchanges.lower() == 'y':
try:
conn.commit()
print ('Table Updated. No. of records updated:', totalupdates)
except cx_Oracle.DatabaseError as error:
print(error)
elif commitchanges.lower() == 'n':
conn.rollback()
print ('Rollback - No updates made to table')
else:
print ('Not a valid selection - Try again')
print (inputattempts)
correct_input = False
return correct_input
then change your while loop to break the loop when
inputattempts = 0
while (inputattempts < 4):
inputattempts += 1
if action(inputattempts):
break
print ('FAILED')
Have your function return a flag telling whether or not the input was accepted:
def action(inputattempts):
commitchanges = input()
if commitchanges.lower() == 'y':
try:
conn.commit()
print ('Table Updated. No. of records updated:', totalupdates)
return True # <-- New
except cx_Oracle.DatabaseError as error:
print(error)
elif commitchanges.lower() == 'n':
conn.rollback()
print ('Rollback - No updates made to table')
return True # <-- New
else:
print ('Not a valid selection - Try again')
print (inputattempts)
return False # <-- New
Now in your loop, you can do
inputattempts = 0
while (inputattempts < 4):
inputattempts += 1
if action(inputattempts):
break
print ('FAILED')
where the break simply exists the loop. Also, I imagine that the print of 'FAILED' should only occur if the loop is exited after the 4 attempts, not if the break was reached. This can be achieved using else. Finally, your while loop really only counts, and so a for loop is more appropriate. Consider
for inputattempts in range(4):
if action(inputattempts):
break
else:
print ('FAILED')
Everytime this piece of code is compiled, I expect it to go through each "if,elif" untill it finds a match. So it can continue to print out the given list on the screen.
But to my surprise even if you input "rifles", all it does is give you the "else" statement.
This is my first post on Stackoverflow, so forgive me if I made some mistake.
Any help is very much appreciated, thanks in advance.
rifles = ["Ak47", "M4A1", "Aug", "Famas", "Galil"]
pistols = ["Glock", "USP", "Deagle", "P250", "Five-7", "Tec-9"]
shotguns = ["Buckshot", "Benelli", "M1319", "Sawed-Off"]
snipers = ["AWP", "SSG", "Cheytac", "Barret", "M24"]
grenades = ["Smoke", "High-Explosive", "Flash", "Concussion", "Molotov", "Incendiary"]
knives = ["Bayonette", "Karambit", "Machete", "Butterfly", "Katana"]
equipment = ["Kevlar", "Helmet", "Tactical-Shield", "Boots", "Nightvision"]
raw_input = input("Search: ")
def search():
if raw_input == "Rifles":
for ri in rifles:
print(ri)
break
elif raw_input is "Pistols":
for pi in pistols:
print(pi)
break
elif raw_input is "Shotguns":
for sho in shotguns:
print(sho)
break
elif raw_input is "Snipers":
for sni in snipers:
print(sni)
break
elif raw_input is "Grenades":
for gre in grenades:
print(gre)
break
elif raw_input is "Knives":
for kni in knives:
print(kni)
elif raw_input is "Equipment":
for equ in equipment:
print(equ)
else:
print("Try again...")
return
search()
You are breaking each loop after you only print one element.
if raw_input == "Rifles":
for ri in rifles:
print(ri)
break
You don't really need the break, so get rid of it and it will work when you type "Rifles"
Your code can be expressed in a much more concise and "pythonic" way:
guns = {
"rifles" : ["Ak47", "M4A1", "Aug", "Famas", "Galil"],
"pistols" : ["Glock", "USP", "Deagle", "P250", "Five-7", "Tec-9"],
"shotguns" : ["Buckshot", "Benelli", "M1319", "Sawed-Off"],
"snipers" : ["AWP", "SSG", "Cheytac", "Barret", "M24"],
"grenades" : ["Smoke", "High-Explosive", "Flash", "Concussion", "Molotov", "Incendiary"],
"knives" : ["Bayonette", "Karambit", "Machete", "Butterfly", "Katana"],
"equipment": ["Kevlar", "Helmet", "Tactical-Shield", "Boots", "Nightvision"],
}
gun = raw_input("Search: ")
gun = gun.lower()
try:
print guns[gun]
except KeyError:
print "No gun of type %s" % gun
But to my surprise even if you input "rifles", all it does is give you the "else" statement.
Your code checks for "Rifles", not "rifles". If you want the two to compare equal, you need to normalise the letter case, for example, like so:
if raw_input.lower() == "rifles":
for ri in rifles:
...
I AM NEW TO PYTHON AND CODING IN GENERAL.
So I have a program with a menu that has multiple functions in it. individually each function works fine on its own, however when i put them together they would usually not fully execute and instead stop half way or wont work at all.
EXAMPLE- the function remove wont remove what i tell it to.
def show_coffee will only show the first description and weight only and nothing else.
What can i do to make the functions fully execute?
import os
def main():
choice =''
fun=[]
while choice != 4:
menu()
choice=getUserChoice()
if choice !=4:
fun=process_choice(choice,fun)
print(fun)
print("Goodby!")
def process_choice(choice,fun):
#fun=fun1
if choice == 0:
fun=add_coffee(fun)
elif choice == 1:
fun=show_coffee(fun)
elif choice == 2:
fun=search_coffee(fun)
elif choice == 3:
fun=modify_coffee(fun)
else:
print(choice,"is not a valid choice.")
return fun
def add_coffee(fun):
another= 'y'
coffee_file=open('coffee.txt', 'a')
Description={}
while another == 'y' or another == 'Y':
print('Enter the following coffee data:')
descr=input('Description: ')
qty= int(input('Quantity (in pounds): '))
coffee_file.write(descr + '\n')
coffee_file.write(str(qty) + '\n')
print("Do you want to add another record?")
another = input("Y=yes, anything else =no: ")
return fun
coffee_file.close()
print('Data append to coffee.txt.')
def show_coffee(fun2):
coffee_file=open ('coffee.txt', 'r')
descr=coffee_file.readline()
while descr != "":
qty= str(coffee_file.readline())
descr=descr.rstrip('\n')
print('Description:', descr)
print('Quantity:', qty)
descr= coffee_file.readline()
fun=fun2
return fun
coffee_file.close()
def search_coffee(fun3):
found=False
search =input('Enter a description to search for: ')
coffee_file=open('coffee.txt', 'r')
descr=coffee_file.readline()
while descr != '':
qty= float(coffee_file.readline())
descr = descr.rstrip('\n')
if descr== search:
print('Description:', descr)
print('Quantity:', qty)
found=True
descr=coffee_file.readline()
fun=fun3
return fun
coffee_file.close()
if not found:
print('That item was not found in the file.')
def modify_coffee(fun4):
found=False
search=input('Which coffee do you want to delete? ')
coffee_file=open('coffee.txt', 'r')
temp_file=open('temp.txt', 'w')
descr=coffee_file.readline()
while descr != '':
qty=float(coffee_file.readline())
descr=descr.rstrip('\n')
if descr !=search:
temp_file.write(descr + '\n')
temp_file.write(str(qty) + '\n')
else:
found=True
descr=coffee_file.readline()
fun=fun4
return fun
coffee_file.close()
temp_file.close()
os.remove('coffee.txt')
os.rename('temp.txt', 'coffee.txt')
if found:
print('The file has been update.')
else:
print('The item was not found in the file.')
def menu():
print('''
0. Add or Update an entry
1. Show an entry
2. Search
3. remove
4. Remove number
''')
def getUserChoice():
choice=-1
while choice <0 or choice > 3:
print("Please select 0-3: ",end='')
choice=int(input())
return choice
You are defining functions but this does not call a function. The standard way to do this in Python is use the if __name__=="__main__": statement at the bottom of a file. When the file is executed (instead of functions/classes being imported by another script) the code block within the scope of if __name__=="__main__": is executed.
Get comfortable with this, it's useful and clean :) Good read - What does if __name__ == "__main__": do?
So, for example...
At the bottom of your file...
if __name__=="__main__":
main()
I'm trying to make a multiple choice survey that allows the user to pick from options 1-x. How can I make it so that if the user enters any characters besides numbers, return something like "That's an invalid answer"
def Survey():
print('1) Blue')
print('2) Red')
print('3) Yellow')
question = int(input('Out of these options\(1,2,3), which is your favourite?'))
if question == 1:
print('Nice!')
elif question == 2:
print('Cool')
elif question == 3:
print('Awesome!')
else:
print('That\'s not an option!')
Your code would become:
def Survey():
print('1) Blue')
print('2) Red')
print('3) Yellow')
while True:
try:
question = int(input('Out of these options\(1,2,3), which is your favourite?'))
break
except:
print("That's not a valid option!")
if question == 1:
print('Nice!')
elif question == 2:
print('Cool')
elif question == 3:
print('Awesome!')
else:
print('That\'s not an option!')
The way this works is it makes a loop that will loop infinitely until only numbers are put in. So say I put '1', it would break the loop. But if I put 'Fooey!' the error that WOULD have been raised gets caught by the except statement, and it loops as it hasn't been broken.
The best way would be to use a helper function which can accept a variable type along with the message to take input.
def _input(message, input_type=str):
while True:
try:
return input_type (input(message))
except:pass
if __name__ == '__main__':
_input("Only accepting integer : ", int)
_input("Only accepting float : ", float)
_input("Accepting anything as string : ")
So when you want an integer , you can pass it that i only want integer, just in case you can accept floating number you pass the float as a parameter. It will make your code really slim so if you have to take input 10 times , you don't want to write try catch blocks ten times.
def func():
choice = "Wrong"
while choice.isdigit()==False :
choice = input("Enter a number: ")
if choice.isdigit()==False:
print("Wrongly entered: ")
else:
return int(choice)
One solution amongst others : use the type function or isinstance function to check if you have an ̀€int or a float or some other type
>>> type(1)
<type 'int'>
>>> type(1.5)
<type 'float'>
>>> isinstance(1.5, int)
False
>>> isinstance(1.5, (int, float))
True
I would catch first the ValueError (not integer) exception and check if the answer is acceptable (within 1, 2, 3) or raise another ValueError exception
def survey():
print('1) Blue')
print('2) Red')
print('3) Yellow')
ans = 0
while not ans:
try:
ans = int(input('Out of these options\(1, 2, 3), which is your favourite?'))
if ans not in (1, 2, 3):
raise ValueError
except ValueError:
ans = 0
print("That's not an option!")
if ans == 1:
print('Nice!')
elif ans == 2:
print('Cool')
elif ans == 3:
print('Awesome!')
return None
I made a module for cases like this called restricted_input which checks the input in real time. Here, since you only need inputs from 1-3, this would do
from restricted_input import r_input
num = int(r_input("Out of these options\(1,2,3), which is your favourite? ", input_type="nothing", allow="123", maxlength=1))
It uses msvcrt.getch/termios to get non-blocking input, so it checks it in real time and allows only the specified characters.
Note: This will not work in IDLEs like Spyder, Jupyter etc.
You can use a module named PyInputPlus.
Installation:
pip install PyInputPlus
You can use this as
def Survey():
print('1) Blue')
print('2) Red')
print('3) Yellow')
question = int(input('Out of these options\(1,2,3), which is your favourite?'))
if question == 1:
print('Nice!')
elif question == 2:
print('Cool')
elif question == 3:
print('Awesome!')
else:
print('That\'s not an option!')