i am trying to make this calculator work but it automatically sends a message please provide a valid number
when i run the command /multiply any help would be muchly appreciated
type here
import telebot
bot = telebot.TeleBot('my token ')
first_number = None
second_number = None
#bot.message_handler(commands=['multiply'])
def multiply(message):
global first_number
global second_number
if first_number is None:
try:
first_number = int(message.text)
bot.send_message(message.chat.id, 'Please provide the second number')
except ValueError:
bot.send_message(message.chat.id, 'Please provide a valid number')
elif second_number is None:
try:
second_number = int(message.text)
result = first_number * second_number
bot.send_message(message.chat.id, 'Result: {}'.format(result))
first_number = None
second_number = None
except ValueError:
bot.send_message(message.chat.id, 'Please provide a valid number')
bot.polling()
i am trying to make it work
The problem with your code was:
You were trying to convert the command message itself to integer.
Your bot did only handle /multiply command but you also want to
handle the further input messages too.
Based on what you said in comments, you wanted the bot to interact in this way
User types /multiply
bot asks for first number
user enter valid first number, if not prompt again to enter a valid number
bot asks for second number, if not prompt again to enter a valid number
first number * second number is displayed
You can use another global variable to denote in which state your bot is. Whether it's in ready state to receive number inputs or not. Also this state is activated when user uses /multiply command and should be deactivated when a calculation is done.
So you can do something like this:
import telebot
bot = telebot.TeleBot('my token')
first_number = None
second_number = None
ready_to_recieve = False
#bot.message_handler(commands=['multiply'])
def multiply_command_handler(message):
global ready_to_recieve
if not ready_to_recieve:
ready_to_recieve = True
bot.send_message(message.chat.id, 'Please provide the first number')
else:
bot.send_message(message.chat.id, 'You have already requested for a calculation')
#bot.message_handler(func=lambda m: ready_to_recieve)
def multiply(message):
global ready_to_recieve
global first_number
global second_number
if first_number is None:
try:
first_number = int(message.text)
bot.send_message(message.chat.id, 'Please provide the second number')
except ValueError:
bot.send_message(message.chat.id, 'Please provide a valid number')
elif second_number is None:
try:
second_number = int(message.text)
result = first_number * second_number
bot.send_message(message.chat.id, 'Result: {}'.format(result))
first_number = None
second_number = None
ready_to_recieve = False
except ValueError:
bot.send_message(message.chat.id, 'Please provide a valid number')
bot.polling()
#bot.message_handler(func=lambda m: ready_to_recieve) this will only get handled when ready_to_recieve is True.
Related
im making a 'guess the number' telegram bot, that is supposed to come up with an integer from 0 to 100. When the user tries to guess the number, bot should give them hints, showing whether their guess is smaller or bigger than the secret number. But it seems to change the secret number every time it recieves a new guess from the user.
Here's the whole code
import random
import telebot
from telebot.types import Message
bot = telebot.TeleBot("-token-")
#bot.message_handler(commands = ('start'))
def guess_number():
a = random.randint(0,100)
a = guess_number.variable
def send_welcome(message):
bot.send_message(message.chat.id, "you entered a guessing game, traveller. Guess a number from 0 to 100, or be eaten by a dragon.")
#bot.message_handler(func=lambda message: True)
def checking(message):
try:
user_message = int(message.text)
if user_message > guess_number.variable:
bot.send_message(message.chat.id, "your number is greater than mine")
elif user_message < guess_number.variable:
bot.send_message(message.chat.id, "your number is smaller than mine")
else:
bot.send_message(message.chat.id, "yep, that's the right number")
except ValueError:
bot.send_message(message.chat.id, "you must enter an integer")
bot.polling()
a = random.randint(0,100) a = guess_number.variable
also it says that the variable 'a',
which is a store for the secret number, is out of reach in guess_number function.
I believe that the variable should be put somewhere else, but can't
figure out where exactly.
For mutliple chats
If you want it to work for multiple users, you'll need a database of some sorts to store a number for each chat. A dictionary could work fine as a small example.
numbers = dict()
#bot.message_handler(commands=('start'))
def guess_number(message):
numbers[message.chat.id] = random.randint(0, 100)
#bot.message_handler(func=lambda message: True)
def checking(message):
try:
user_message = int(message.text)
if user_message > numbers[message.chat.id]:
bot.send_message(message.chat.id, "your number is greater than mine")
elif user_message < numbers[message.chat.id]:
bot.send_message(message.chat.id, "your number is smaller than mine")
else:
bot.send_message(message.chat.id, "yep, that's the right number")
except ValueError:
bot.send_message(message.chat.id, "you must enter an integer")
except (TypeError, KeyError):
bot.send_message(message.chat.id, "there's no number to guess! say /start to start")
For a single chat
If you only need this bot to work for a single chat, you could opt to use a single global variable to store the secret number. Then make it accessible within functions with the global keyword.
the_number = None
#bot.message_handler(commands=('start'))
def guess_number(message):
global the_number
the_number = random.randint(0, 100)
#bot.message_handler(func=lambda message: True)
def checking(message):
global the_number
try:
user_message = int(message.text)
if user_message > the_number:
bot.send_message(message.chat.id,"your number is greater than mine")
elif user_message < the_number:
bot.send_message(message.chat.id,"your number is smaller than mine")
else:
bot.send_message(message.chat.id, "yep, that's the right number")
except ValueError:
bot.send_message(message.chat.id, "you must enter an integer")
In either case, the numbers will be lost when the bot is off.
Choose what fits and keep this in mind
This question already has answers here:
What is the intended use of the optional "else" clause of the "try" statement in Python?
(22 answers)
Closed 1 year ago.
Just started learning python and wanted to make a calculator. I currently have some code that tries to turn what the user inputs into an integer, but what I want to do is be able to check if the attempt was successful or not.
Here is the part i'm having trouble with.
import sys
first_number = input('Enter a number: ')
try:
int(first_number)
except:
print("Sorry, that's not a number.")
exit()
You can just do:
try:
int(first_number)
print("try successful!")
except ValueError:
print("Sorry, that's not a number.")
print("try unsuccessful!")
exit()
You can set a flag after int that is only set on success:
success=False
nums=iter(['abc','123'])
while not success:
try:
x=int(next(nums))
success=True
except ValueError as e:
print(e, 'Try Again!')
print(x)
Prints:
invalid literal for int() with base 10: 'abc' Try Again!
123
First time with 'abc' is an error, second time a success.
Since nums first try is an error, that will not set success to True. Second time is not an error, success is set to True and the while loop terminates. You can use the same method with user input. The iterator is just simulating that...
So for your example:
success=False
while not success:
try:
n_string = input('Enter a number: ')
int(n_string)
success=True
except ValueError as e:
print(f'"{n_string}" is not a number. Try again')
Which is commonly simplified into this common idiom in Python for user input:
while True:
try:
n_string = input('Enter a number: ')
int(n_string)
break
except ValueError as e:
print(f'"{n_string}" is not a number. Try again')
To have this make more sense, make it a function:
def getNumber():
while True:
number = input('Enter a number: ')
if number.isnumeric():
return int(number)
print( "Not a number, please try again." )
Here is my code:
import pickle
current_user = None
class User:
def __init__(self, username, password):
self.username = username
self.password = password
def set_password(self):
self.password = input("Enter NEW password > ")
def __get_password(self):
return self.password
def __get_username(self):
return self.username
def change_password(self):
my_password = input("Enter your CURRENT password > ")
if my_password == self.__get_password():
self.set_password()
else:
print("Please try again")
def display_details(self):
print()
print("Username and password")
print("---------------------")
print("username is: ", User.__get_username(self))
print("password is: ", User.__get_password(self))
print()
def __repr__(self):
return f'username: {self.username}'
try:
users = pickle.load(open("users.pickle", "rb"))
except (OSError, IOError) as f:
users = [User("MichaelPalin", "P4rr0t"), User("EricIdle", "M0nty"), User("TerryJones", "Pyth0n")]
pickle.dump(foo, open("users.pickle", "wb"))
def find_user(name):
for user in users:
if user.username == name:
return user
def add_user():
user = input("Enter NEW user > ")
password = input(f"Enter password for {user} > ")
users.append(User(user, password))
def delete_user():
delete_user = input("Enter the user you wish to remove > ")
user = find_user(delete_user)
if user:
users.remove(user)
print('done')
else:
print(f'user {delete_user} not found')
def display_users():
for user in users:
print(user)
def invalid_entry(): # Response for invalid entries to menu.
print("Invalid entry, please try again")
print()
def menu(): # Display menu, prompt for and accept keyboard choice
print("Please select one of the following:")
print()
print("Enter a if you want to add a new user")
print("Enter d if you want to delete a user")
print("Enter f if you want to find a user")
print("Enter c if you want to change your password")
print("Enter u if you want to display a list of users")
print("Enter q if you want to Quit")
choice = input("")
return choice
while True:
menu_choice = menu()
if menu_choice.lower() == "a":
add_user()
elif menu_choice.lower() == "d":
delete_user()
elif menu_choice.lower() == "f":
current_user = find_user()
elif menu_choice.lower() == "c":
if current_user is None:
print("No user selected!")
continue
else:
current_user.change_password()
elif menu_choice.lower() == 'u':
display_users()
elif menu_choice.lower() == "q":
print("Goodbye")
with open('users.pickle', 'wb') as f:
pickle.dump(users, f)
quit()
else:
invalid_entry()
There's clearly something wrong as it's getting stuck in a loop:
Enter your CURRENT password > password
Enter your CURRENT password > password
Enter your CURRENT password >
I can see PyCharm is coming up 'local variable my_password is not used' too.
I tried removing my_password = input("Enter your CURRENT password > ") from the def change_password() block, but that just results in a fatal error.
I also tried renaming the first change_password function to update_password and updating the second one accordingly, so that it went...
def change_password():
update_password()
...but that didn't work either.
This is the logic that I want to use:
IF the user selects 'c' in the menu THEN do the following...
Prompt the user to enter their current password
IF the entered input matches their current password THEN prompt them to enter a new password and update their password accordingly
IF the entered input does not match their current password THEN prompt them to try again
Any help please? TIA
By the way, I'm puzzled that PyCharm is coming up 'unresolved reference 'foo''. That section seems to work OK, but any insights on why that is and if it's a problem or not would be appreciated.
Edit: I've updated the code in line with the suggestions, as much as I can, anyway.
Edit 2: PyCharm said that self in if my_password == self.__get_password(self) is an unexpected argument, so I removed it, and that didn't seem to do any harm.
You're not stuck in a loop, you stuck in recursion
def change_password():
my_password = input("Enter your CURRENT password > ")
change_password()
notice that you just keep calling change password over and over... also you have double methods for some reason, use the ones in you User class.
when 'c' is chosen you have no context, you don't know WHO is trying to change their password, so first you must ask who the user is, try the following changes:
before your while true loop put current_user = None
change the entry for 'f' to be current_user = find_user()
and the entry for 'c' to be
if current_user is None:
print("No user selected!")
continue
else:
current_user.change_password()
The other change_password function in the outer scope also requests command line input. try to eliminate all the unneeded
input("Enter your CURRENT password > ")
except for one and use parameters in your function calls instead.
On top of that, the outer scope change_password() function is calling itself over and over, because its shadowing the inner one. Try renaming one of the two.
I am pretty new to python and as a project to push myself, I decided to create a simple framework with an updatable user:password dictionary. This is still a work in progress! The problem exists when creating a new user id and then trying to access that user id. I am using python 3.7.
Here is the error:
Traceback (most recent call last):
line 37, in
if account in accounts:
TypeError: argument of type 'NoneType' is not iterable
import sys
accounts = {'Trace': 'Jollyrancher5', 'Brian': 'Kitties82', 'Taylor': 'Flower15'}
while True:
print('Please select an option.\n1. Create new account.\n2. Enter existing account.')
choice = input()
if choice == '1':
print('Please enter an account name')
new_account = input()
if new_account not in accounts.keys():
print('Please enter a password.')
new_pass = input()
accounts = accounts.update({new_account: new_pass})
print('Your new User ID is: ' + new_account + '.')
print('Your new password is: ' + new_pass + '.')
print('Please store this information for safe keeping.')
print('Type OK to continue.')
while True:
next = input()
if next == 'OK' or next == 'ok':
break
else:
print('Invalid entry. Please type OK.')
else:
print('Account name taken. Please enter a different account name.')
elif choice == '2':
break
else:
print('Not a valid entry.')
account = ''
password = ''
denial = 0
while True:
print('Please enter User ID.')
account = input()
if account in accounts:
break
else:
print('User ID not recognized.')
while True:
print('Please enter password.')
password = input()
if password == accounts[account]:
break
else:
password != accounts[account]
denial += 1
if denial == 3:
print('Account locked.')
input()
sys.exit()
print('Access Granted.\nYour account balance is $1,000,000.00.')
input()
The issue is in line no 13:
accounts = accounts.update({new_account: new_pass})
This returns None as the update is done in place. [see docs] Instead use:
accounts.update({new_account: new_pass})
It will perform the update no need to reassign the value.
Remove this line:-
`accounts = accounts.update({new_account: new_pass})`
add this line:-
`while True:
print('Please enter User ID.')
account = input()
accounts.update({new_account:new_pass})
if account in accounts:`
this error is caused because your dictionary was not getting updated, and that's why the first value it was recieving was None hence a NoneType error was generated.
Upvote if you understand my answer.
So I am making a prime number detector as a project. I’m VERY new to programming and my friend showed me a little python. I want to make a function that detects if the user puts in a number for the input (like 5,28,156,42,63) and if the put in something else (like banana,pants,or cereal) to give them a custom error saying "Invalid Number. Please Try Again" and then looping the program until they put in a number.
Please help me make this work.
def number_checker():
user_number = int(input('Please enter a Number: '))
check = isinstance(user_number, int)
if check == True:
print ('This is a number')
if check == False:
print ('This is not a number')
1) Casting input to int would raise an exception if the input string cannot be converted to int.
user_number = int(input('Please enter a Number: '))
^^^
2) It does not make sense to cross-verify user_number with int instance as it would already be int
3) You can try
def number_checker():
while not input("enter num: ").isdigit():
print("This is not a number")
print("This is a number")
number_checker()
Try following:
def number_checker():
msg = 'Put your number > '
while True:
user_input = input(msg)
correct = user_input.isdigit()
if correct:
print("This is an integer")
return # here you can put int(user_input)
else:
print("This is not an integer")
msg = 'You typed not integer. Try again.> '
if __name__ == '__main__':
number_checker()
And it's also good rule give names for your functions as verbs according to what they do. For this one, I would give, for example def int_input or something.