I have an IRC bot that I made for automating stuff.
Here's a snippet of it:
def analyseIRCText(connection, event):
global adminList, userList, commandPat, flood
userName = extractUserName(event.source())
userCommand = event.arguments()[0]
escapedChannel = cleanUserCommand(config.channel).replace('\\.', '\\\\.')
escapedUserCommand = cleanUserCommand(event.arguments()[0])
#print userName, userCommand, escapedChannel, escapedUserCommand
if flood.has_key(userName):
flood[userName] += 1
else:
flood[userName] = 1
... (if flood[userName] > certain number do...)
So the idea is that flood thing is a dictionary where a list of users who have entered in a command to the bot in the recent... some time is kept, and how many times they've said so and so within that time period.
Here's where I run into trouble. There has to be SOMETHING that resets this dictionary so that the users can say stuff every once in awhile, no? I think that a little thing like this would do the trick.
def floodClear():
global flood
while 1:
flood = {} # Clear the list
time.sleep(4)
But what would be the best way to do this?
At the end of the program, I have a little line called:
thread.start_new_thread(floodClear,())
so that this thing doesn't get called at gets stuck in an infinite loop that halts everything else. Would this be a good solution or is there something better that I could do?
Your logic should be enough. If you have say:
if flood.has_key(userName):
flood[userName] += 1
else:
flood[userName] = 1
if flood[userName] > say 8:
return 0
That should make your bot ignore the user if he has spammed too many times within your given time period. What you have there should also work to clear up your flood dictionary.
Related
I might be asking a simple question. I have a python program that runs every minute. But I would like a block of code to only run once the condition changes? My code looks like this:
# def shortIndicator():
a = int(indicate_5min.value5)
b = int(indicate_10min.value10)
c = int(indicate_15min.value15)
if a + b + c == 3:
print("Trade posible!")
else:
print("Trade NOT posible!")
# This lets the processor work more than it should.
"""run_once = 0 # This lets the processor work more than it should.
while 1:
if run_once == 0:
shortIndicator()
run_once = 1"""
I've run it without using a function. But then I get an output every minute. I've tried to run it as a function, when I enable the commented code it sort of runs, but also the processing usage is more. If there perhaps a smarter way of doing this?
It's really not clear what you mean, but if you only want to print a notification when the result changes, add another variable to rembember the previous result.
def shortIndicator():
return indicate_5min.value5 and indicate_10min.value10 and indicate_15min.value15
previous = None
while True:
indicator = shortIndicator()
if previous is None or indicator != previous:
if indicator:
print("Trade possible!")
else:
print("Trade NOT possible!")
previous = indicator
# take a break so as not to query too often
time.sleep(60)
Initializing provious to None creates a third state which is only true the first time the while loop executes; by definition, the result cannot be identical to the previous result because there isn't really a previous result the first time.
Perhaps also notice the boolean shorthand inside the function, which is simpler and more idiomatic than converting each value to an int and checking their sum.
I'm guessing the time.sleep is what you were looking for to reduce the load of running this code repeatedly, though that part of the question remains really unclear.
Finally, check the spelling of possible.
If I understand it correctly, you can save previous output to a file, then read it at the beginning of program and print output only if previous output was different.
So I have been trying to find out a more beautiful way to actually do some fault and errors in a script I am working on.
Basically I have a json_resp = resp.json() who either gives me values or [] meaning either there is something or not.
Now the question I am having trouble with is that I don't know which way is the best to repeat a function if it is empty, shall I repeat the whole function or what else would be most "best reason" to solve it in a good way?
What I have done is that I changed the objects from the json resp to a len. If its 0 then repeat else do other stuff:
#json_resp['objects'] either has empty [] or not always.
json_resp = resp.json()
if len(json_resp['objects']) == 0:
print('Sleeping in 2 sec')
time.sleep(2)
run_method() #Shall I call the function to start over?
else:
print(len(json_resp['objects']))
continue do rest of the code
As you can see right now I am compare with len of the json_resp but what makes me unsure is that if it is a good way to actually call the function again? Wouldn't it have a limit or maybe delay the whole process... Im not sure but what is your thoughts of making this function "better, smarter, faster"?
My thought was maybe to either put a try except or while loop that? Let me know what you guys think
Python lists are faulty so you can just use if json_resp:
You can use recursion. Just make sure you have somewhere to break
I'd like to revise your code into:
max_iteration = 5
current_iteration = 0
def run_method():
current_iteration += 1
# Do other stuff. Requests I guess?
response = resp.json
if response:
# do something with the response
else:
if current_iteration == max_iteration:
return 'Maximum iterations reached: {}'.format(max_iteration)
timer = 2
print('Sleeping in {} seconds'.format(timer))
time.sleep(timer)
run_method()
I have 5 players where they throw dice. We cannot use any external input such as onclick action or something.
How do I make the computer decide whether it is good to stop throwing? The stopping criteria is either you didn't throw 1,5 or straight or triples or higher. Everything counts as a point and if you hit something, lets say triple sixes you now can decide whether you throw again, but without these three dice. But if you fail to hit anything on the next throw, you lose every point you've got in the section. Or keep the sixes, which gives you 600 points.
def game(length, output = True):
round_no = 0
avg_pts = 0
player_points[0,0,0,0,0]
while output:
round_no += 1
for i in range 5:
lock = true
while lock:
dice_throw(number_of_throws)
def dice_throw(number_of_throws):
throw_values = []
for i in range(number_of_throws):
throw_values.append(randint(1,6))
throw_values.sort()
for i in range(throw_values)
How can I make a mechanism that decides if its good to continue throwing or not?
I am currently a new student learning python. This is my first real experience doing much computer coding. For my project I must create a fill in the blank quiz with three different levels of difficulty. Once the user chooses a difficulty the game should print a different paragraph based on the difficulty. Each section of the game works fine but I am having trouble creating the "difficulty chooser." No matter the difficulty I choose, the game rolls through the easy, medium, and the hard level in order and then crashes.
Below I have included the introductory text and the difficulty chooser. I would love some help. I am sure there are really obvious things I don't see. Thank you!
def introduction():
print '''Welcome to Kevin's European Geography Quizzes.
Test your knowledge of European geography. \n'''
difficulty = raw_input('''Do you want to play an easy, medium, or hard game?
Please type the number 1 for easy, 2 for medium, or 3 for hard.\n''' )
game_chooser(difficulty)
def game_chooser(difficulty):
cursor = 0
difficulty_choice = [easy_game(), medium_game(), hard_game()]
#each element of the above list links to a procedure and starts one of the
#mini-games.
while cursor < len(difficulty_choice):
if difficulty != cursor:
cursor += 1
else:
difficulty_choice[cursor]
break
You can do with if else if you only want to print something but if you have separate code block for each level then define a function for each level and use this pattern :
You can define the function blocks and call them basis on user input something like:
# define the function blocks
def hard():
print ("Hard mode code goes here.\n")
def medium():
print ("medium mode code goes here\n")
def easy():
print ("easy mode code goes here\n")
def lazy():
print ("i don't want to play\n")
# Now map the function to user input
difficulty_choice = {0 : hard,
1 : medium,
4 : lazy,
9 : easy,
}
user_input=int(input("which mode do you want to choose : \n press 0 for hard \n press 1 for medium \n press 4 for lazy \n press 9 for easy "))
difficulty_choice[user_input]()
Then invocation of function block will be:
difficulty_choice[num]()
Add a conditional for the input.
if difficulty == 'easy':
print("here is an easy game")
elif difficulty == 'medium':
print('here is a medium game')
elif difficulty == 'hard':
print('here is hard')
else:
print('Please enter valid input (easy, medium, hard)')
Under each if statement put your game code.
The reason your code goes through all the difficulties is because of this line:
difficulty_choice = [easy_game(), medium_game(), hard_game()]
When Python sees something like easy_game(), it calls the easy_game function and replaces it with the result. You don't want to call the function yet though, so you can take off the parenthesis to store just the function instead:
difficulty_choice = [easy_game, medium_game, hard_game]
This will mean you have to call the function after you take it out of the array.
As for the crash, when you use raw_input() you get a string back. That means when you type in the 1 to decide for an easy game, you get the character 1, which is represented by the number 49. That's why your code goes through everything and crashes: Your 1 is really a 49. In fact, if you type 1 < '1' into the interpreter, you'll get True back.
To fix that, you can pass the result of raw_input() to the int() function, which will parse it and give you the proper integer (or throw an exception if it can't be parsed). The last line of introduction would then look like game_chooser(int(difficulty)).
You could also skip most of the code of game_chooser by just indexing into the array (that's what they're for, after all):
def game_chooser(difficulty):
# the lack of parens here means you get the function itself, not what it returns
difficulty_choice = [easy_game, medium_game, hard_game]
#each element of the above list links to a procedure and starts one of the
#mini-games.
# note the parens to actually call the retrieved function now
difficulty_choice[difficulty]()
just registered so I could ask this question.
Right now I have this code that prevents a class from updating more than once every five minutes:
now = datetime.now()
delta = now - myClass.last_updated_date
seconds = delta.seconds
if seconds > 300
update(myClass)
else
retrieveFromCache(myClass)
I'd like to modify it by allowing myClass to update twice per 5 minutes, instead of just once.
I was thinking of creating a list to store the last two times myClass was updated, and comparing against those in the if statement, but I fear my code will get convoluted and harder to read if I go that route.
Is there a simpler way to do this?
You could do it with a simple counter. Concept is get_update_count tracks how often the class is updated.
if seconds > 300 or get_update_count(myClass) < 2:
#and update updatecount
update(myClass)
else:
#reset update count
retrieveFromCache(myClass)
Im not sure how you uniquely identify myClass.
update_map = {}
def update(instance):
#do the update
update_map[instance] = update_map.get(instance,0)+1
def get_update_count(instance):
return update_map[instance] or 0