简体   繁体   中英

why does this python while loop not work in the program?

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 ie 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))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM