I am creating a little script which check the number of mail in my gmail account and print them in the
status bar. The function gmail() returns the number of new emails. I have few questions, but first this is the code I wrote so far (clearly I am a novice):
class MyApplicationAppDelegate(NSObject):
var = 1
def applicationDidFinishLaunching_(self, sender):
NSLog("Application did finish launching.")
global ngmail
self.statusItem = NSStatusBar.systemStatusBar().statusItemWithLength_(NSVariableStatusItemLength)
while var == 1 :
ngmail2 = gmail();
if ngmail2 !=ngmail:
self.statusItem.setTitle_("loading")
self.statusItem.setTitle_(ngmail2)
ngmail = ngmail2
time.sleep(6)
1) Why do I need the line "self.statusItem.setTitle_("loading")" ? without that line it wouldn't update itself. I really do not know why.
2) it runs as it should, but whenever I get close to the number in the status bar, the spinning wheel appear.
I guess the reason is because I am using while, and instead I should be using something like nsrunloop or something like that. Can anyone advice on this?
3) If I put my mac to sleep and I wake it up, the script stops working. Any solution? maybe this is related to question 2) above.
Thanks!
All of your problems come from the fact that you're blocking the main thread.
In Cocoa, or almost any other GUI framework, the main thread runs a loop that waits for the next event, calls an event handler, and repeats until quit.
Your event handler, applicationDidFinishLaunching_, never returns. This means Cocoa can never handle the next event. Eventually, the OS will notice that you're not responding and put up the beachball.
With Cocoa, sometimes it sneaks in some other events each time you give it a chance, like on the setTitle_ calls, and there are some things the OS can fake even if you're not responding, like keeping the window redrawing, so it isn't always obvious that your app is not responsive. But that doesn't mean you don't need to solve the problem.
There are a number ways to do this, but is the easiest is probably to use a background thread. Then, applicationDidFinishLaunching_ can kick off the background thread and then return immediately, allowing the main thread to get back to its job handling events.
The only tricky bit is that code running on background threads can't make calls to UI objects. So, what do you do about that?
That's what performSelectorOnMainThread_withObject_waitUntilDone_ is for.
Here's an example:
class MyApplicationAppDelegate(NSObject):
var = 1
def background_work(self):
global ngmail
while var == 1 :
ngmail2 = gmail();
if ngmail2 !=ngmail:
self.statusItem.setTitle_("loading")
self.statusItem.performSelectorOnMainThread_withObject_waitUntilDone_('setTitle:', ngmail2, False)
time.sleep(6)
def applicationDidFinishLaunching_(self, sender):
NSLog("Application did finish launching.")
self.statusItem = NSStatusBar.systemStatusBar().statusItemWithLength_(NSVariableStatusItemLength)
self.background_worker = threading.Thread(target=self.background_work)
self.background_worker.start()
The only tricky bit is that you have to use the ObjC name for the selector (setTitle:), not the Python name (setTitle_).
However, your code has another subtle bug: var isn't actually synchronized, so it's possible for you to change its value in the main thread, without the background thread ever noticing.
On top of that, doing a sleep(6) means that it will take up to 6 seconds to quit your app, because the background thread won't get to the code that checks var until it finishes sleeping.
You can fix both of these by using a Condition.
class MyApplicationAppDelegate(NSObject):
var = 1
condition = threading.Condition()
def background_work(self):
global ngmail
with condition:
while var == 1:
ngmail2 = gmail();
if ngmail2 != ngmail:
self.statusItem.performSelectorOnMainThread_withObject_waitUntilDone_('setTitle:', ngmail2, False)
condition.wait(6)
#classmethod
def shutdown_background_threads(cls):
with condition:
var = 0
condition.notify_all()
(I assume you used a class attribute for var instead of an instance attribute on purpose, so I likewise made the condition a class attribute and the shutdown method a class method.)
Related
Using PyGubu (tool to create Tkinter interfaces) I obtained the following GUI:
Current situation:
When I click the Button "Create", a function is called. This function takes quite some time, and the graphical interfaces is just frozen. As I would like to keep the graphical interface and the functional part as much separated as possible, I don't want to update the Progress Bar or the interface in general from the function I call
Desired situation
The best case for me would be a solution without Threading: I would like, upon clicking "Create", that my function runs, while the Progress Bar updates itself (just to show a feedback to the user, and to tell him "look, I am doing something") and the interface remains responsive, so the user can actually interact with it while the function finish.
Current attempts
I tried to solve this using Threading:
#I have this code in my main.py:
from threading import Thread
from queue import Queue, Empty
my_queue=Queue()
#And this is a simplified version of the Command of the "Create" Button:
def create_command(self):
#Show the progress bar and start it
self.show_item(self.progress)
self.progress.start()
#Run the big function
thrd = Thread(target = my_big_function, args=(some_arguments, my_queue))
thrd.start()
do_retry = True
while do_retry: #Repeat until you have a result
try:
result = my_queue.get(False) #If you have a result, exit loop. Else, throw Empty
do_retry = False
except Empty: #Queue is still empty
self.progress_var.set(self.progress_var.get()+1)
sleep(0.05)
self.mainwindow.update() #Update the progress bar
q.task_done()
self.progress.stop()
Problem of the current attempt
As I am not used to work with threads, I am facing two problems:
In some runs (not all of them, just some) I have a RuntimeError stating
RuntimeError: main thread is not in main loop
I tried to overcome this looking at other question in StackOverflow, but now it just happens randomly, and I don't know how to avoid it. The module mtTinker is no more maintained for python 3.x (there is a vague attempt full of ToDoes and blood)
If there is some kind of exception in the big function, I don't know how to handle it. The program would just run forever waiting for a result that will never come back
So
How can I obtain my desired outcome? Thanks in advance
You can try adding root.update() inside the function you call, inside the main loop. Hope that's helpful!
I'm trying to connect to a TeamSpeak server using the QueryServer to make a bot. I've taken advice from this thread, however I still need help.
This is The TeamSpeak API that I'm using.
Before the edits, this was the summary of what actually happened in my script (1 connection):
It connects.
It checks for channel ID (and it's own client ID)
It joins the channel and starts reading everything
If someone says an specific command, it executes the command and then it disconnects.
How can I make it so it doesn't disconnect? How can I make the script stay in a "waiting" state so it can keep reading after the command is executed?
I am using Python 3.4.1.
I tried learning Threading but either I'm dumb or it doesn't work the way I thought it would. There's another "bug", once waiting for events, if I don't trigger anything with a command, it disconnects after 60 seconds.
#Librerias
import ts3
import threading
import datetime
from random import choice, sample
# Data needed #
USER = "thisisafakename"
PASS = "something"
HOST = "111.111.111.111"
PORT = 10011
SID = 1
class BotPrincipal:
def __init__(self, manejador=False):
self.ts3conn = ts3.query.TS3Connection(HOST, PORT)
self.ts3conn.login(client_login_name=USER, client_login_password=PASS)
self.ts3conn.use(sid=SID)
channelToJoin = Bot.GettingChannelID("TestingBot")
try: #Login with a client that is ok
self.ts3conn.clientupdate(client_nickname="The Reader Bot")
self.MyData = self.GettingMyData()
self.MoveUserToChannel(ChannelToJoin, Bot.MyData["client_id"])
self.suscribirEvento("textchannel", ChannelToJoin)
self.ts3conn.on_event = self.manejadorDeEventos
self.ts3conn.recv_in_thread()
except ts3.query.TS3QueryError: #Name already exists, 2nd client connect with this info
self.ts3conn.clientupdate(client_nickname="The Writer Bot")
self.MyData = self.GettingMyData()
self.MoveUserToChannel(ChannelToJoin, Bot.MyData["client_id"])
def __del__(self):
self.ts3conn.close()
def GettingMyData(self):
respuesta = self.ts3conn.whoami()
return respuesta.parsed[0]
def GettingChannelID(self, nombre):
respuesta = self.ts3conn.channelfind(pattern=ts3.escape.TS3Escape.unescape(nombre))
return respuesta.parsed[0]["cid"]
def MoveUserToChannel(self, idCanal, idUsuario, passCanal=None):
self.ts3conn.clientmove(cid=idCanal, clid=idUsuario, cpw=passCanal)
def suscribirEvento(self, tipoEvento, idCanal):
self.ts3conn.servernotifyregister(event=tipoEvento, id_=idCanal)
def SendTextToChannel(self, idCanal, mensajito="Error"):
self.ts3conn.sendtextmessage(targetmode=2, target=idCanal, msg=mensajito) #This works
print("test") #PROBLEM HERE This doesn't work. Why? the line above did work
def manejadorDeEventos(sender, event):
message = event.parsed[0]['msg']
if "test" in message: #This works
Bot.SendTextToChannel(ChannelToJoin, "This is a test") #This works
if __name__ == "__main__":
Bot = BotPrincipal()
threadprincipal = threading.Thread(target=Bot.__init__)
threadprincipal.start()
Prior to using 2 bots, I tested to launch the SendTextToChannel when it connects and it works perfectly, allowing me to do anything that I want after it sends the text to the channel. The bug that made entire python code stop only happens if it's triggered by the manejadorDeEventos
Edit 1 - Experimenting with threading.
I messed it up big time with threading, getting to the result where 2 clients connect at same time. Somehow i think 1 of them is reading the events and the other one is answering. The script doesn't close itself anymore and that's a win, but having a clone connection doesn't looks good.
Edit 2 - Updated code and actual state of the problem.
I managed to make the double connection works more or less "fine", but it disconnects if nothing happens in the room for 60 seconds. Tried using Threading.timer but I'm unable to make it works. The entire question code has been updated for it.
I would like an answer that helps me to do both reading from the channel and answering to it without the need of connect a second bot for it (like it's actually doing...) And I would give extra points if the answer also helps me to understand an easy way to make a query to the server each 50 seconds so it doesn't disconnects.
From looking at the source, recv_in_thread doesn't create a thread that loops around receiving messages until quit time, it creates a thread that receives a single message and then exits:
def recv_in_thread(self):
"""
Calls :meth:`recv` in a thread. This is useful,
if you used ``servernotifyregister`` and you expect to receive events.
"""
thread = threading.Thread(target=self.recv, args=(True,))
thread.start()
return None
That implies that you have to repeatedly call recv_in_thread, not just call it once.
I'm not sure exactly where to do so from reading the docs, but presumably it's at the end of whatever callback gets triggered by a received event; I think that's your manejadorDeEventos method? (Or maybe it's something related to the servernotifyregister method? I'm not sure what servernotifyregister is for and what on_event is for…)
That manejadorDeEventos brings up two side points:
You've declared manejadorDeEventos wrong. Every method has to take self as its first parameter. When you pass a bound method, like self.manejadorDeEventos, that bound self object is going to be passed as the first argument, before any arguments that the caller passes. (There are exceptions to this for classmethods and staticmethods, but those don't apply here.) Also, within that method, you should almost certainly be accessing self, not a global variable Bot that happens to be the same object as self.
If manejadorDeEventos is actually the callback for recv_in_thread, you've got a race condition here: if the first message comes in before your main threads finishes the on_event assignment, the recv_on_thread won't be able to call your event handler. (This is exactly the kind of bug that often shows up one time in a million, making it a huge pain to debug when you discover it months after deploying or publishing your code.) So, reverse those two lines.
One last thing: a brief glimpse at this library's code is a bit worrisome. It doesn't look like it's written by someone who really knows what they're doing. The method I copied above only has 3 lines of code, but it includes a useless return None and a leaked Thread that can never be joined, not to mention that the whole design of making you call this method (and spawn a new thread) after each event received is weird, and even more so given that it's not really explained. If this is the standard client library for a service you have to use, then you really don't have much choice in the matter, but if it's not, I'd consider looking for a different library.
In my class that inherits wx.Panel, I have this method:
def KeyEventProcedure(self):
while True:
z = msvcrt.getch()
if ord(z) == 27:
self.OutputText("Stopping.")
self.program_stopped = True
print "IT'S WORKIIIIING"
And in the __init__ method of my PanelClass, I have this:
self.program_stopped = False
keyThread = Thread(target = self.KeyEventProcedure)
#keyThread.setDaemon(1) //I tried with and without this call, makes no difference
keyThread.start()
And in many places in my app I have this check:
if self.program_stopped == True:
self.program_stopped = False
return
I know I can quit the whole app in the KeyEventProcedure method, but I don't want to quit the app, I just want the currently executing function to return. However when I start the app, no matter how many times I press ESC, it doesn't print and the currently executing operation doesn't return.
If all you want to do is catch key presses, you should just use wxPython's built-in capabilities for that. Try binding to wx.EVT_KEY_DOWN or even wx.EVT_CHAR instead of using this Windows-only method. See the following:
http://www.blog.pythonlibrary.org/2009/08/29/wxpython-catching-key-and-char-events/
Also, you should not try to access a wxPython program from a thread directly. If you need to update the UI from a thread, then you must use a wxPython thread-safe method, such as wx.CallAfter or wx.PostEvent. See the following for additional information:
http://wiki.wxpython.org/LongRunningTasks
http://www.blog.pythonlibrary.org/2010/05/22/wxpython-and-threads/
I've tried posting this in the reverse-engineering stack-exchange, but I thought I'd cross-post it here for more visibility.
I'm having trouble switching from debugging one thread to another in pydbg. I don't have much experience with multithreading, so I'm hoping that I'm just missing something obvious.
Basically, I want to suspend all threads, then start single stepping in one thread. In my case, there are two threads.
First, I suspend all threads. Then, I set a breakpoint on the location where EIP will be when thread 2 is resumed. (This location is confirmed by using IDA). Then, I enable single-stepping as I would in any other context, and resume Thread 2.
However, pydbg doesn't seem to catch the breakpoint exception! Thread 2 seems to resume and even though it MUST hit that address, there is no indication that pydbg is catching the breakpoint exception. I included a "print "HIT BREAKPOINT" inside pydbg's internal breakpoint handler, and that never seems to be called after resuming Thread 2.
I'm not too sure about where to go next, so any suggestions are appreciated!
dbg.suspend_all_threads()
print dbg.enumerate_threads()[0]
oldcontext = dbg.get_thread_context(thread_id=dbg.enumerate_threads()[0])
if (dbg.disasm(oldcontext.Eip) == "ret"):
print disasm_at(dbg,oldcontext.Eip)
print "Thread EIP at a ret"
addrstr = int("0x"+(dbg.read(oldcontext.Esp + 4,4))[::-1].encode("hex"),16)
print hex(addrstr)
dbg.bp_set(0x7C90D21A,handler=Thread_Start_bp_Handler)
print dbg.read(0x7C90D21A,1).encode("hex")
dbg.bp_set(oldcontext.Eip + dbg.instruction.length,handler=Thread_Start_bp_Handler)
dbg.set_thread_context(oldcontext,thread_id=dbg.enumerate_threads()[0])
dbg.context = oldcontext
dbg.resume_thread(dbg.enumerate_threads()[0])
dbg.single_step(enable=True)
return DBG_CONTINUE
Sorry about the "magic numbers", but they are correct as far as I can tell.
One of your problems is that you try to single step through Thread2 and you only refer to Thread1 in your code:
dbg.enumerate_threads()[0] # <--- Return handle to the first thread.
In addition, the code the you posted is not reflective of the complete structure of your script, which makes it hard to judge wether you have other errors or not. You also try to set breakpoint within the sub-brach that disassembles your instructions, which does not make a lot of sense to me logically. Let me try to explain what I know, and lay it out in an organized manner. That way you might look back at your code, re-think it and correct it.
Let's start with basic framework of debugging an application with pydbg:
Create debugger instance
Attache to the process
Set breakpoints
Run it
Breakpoint gets hit - handle it.
This is how it could look like:
from pydbg import *
from pydbg.defines import *
# This is maximum number of instructions we will log
MAX_INSTRUCTIONS = 20
# Address of the breakpoint
func_address = "0x7C90D21A"
# Create debugger instance
dbg = pydbg()
# PID to attach to
pid = int(raw_input("Enter PID: "))
# Attach to the process with debugger instance created earlier.
# Attaching the debugger will pause the process.
dbg.attach(pid)
# Let's set the breakpoint and handler as thread_step_setter,
# which we will define a little later...
dbg.bp_set(func_address, handler=thread_step_setter)
# Let's set our "personalized" handler for Single Step Exception
# It will get triggered if execution of a thread goes into single step mode.
dbg.set_callback(EXCEPTION_SINGLE_STEP, single_step_handler)
# Setup is done. Let's run it...
dbg.run()
Now having the basic structure, let's define our personalized handlers for breakpoint and single stepping. The code snippet below defines our "custom" handlers. What will happen is when breakpoint hits we will iterate through threads and set them to single step mode. It will in turn trigger single step exception, which we will handle and disassemble MAX_INSTRUCTIONS amount of instructions:
def thread_step_setter(dbg):
dbg.suspend_all_threads()
for thread_id in dbg.enumerate_threads():
print "Single step for thread: 0x%08x" % thread_id
h_thread = dbg.open_thread(thread_id)
dbg.single_step(True, h_thread)
dbg.close_handle(h_thread)
# Resume execution, which will pass control to step handler
dbg.resume_all_threads()
return DBG_CONTINUE
def single_step_handler(dbg):
global total_instructions
if instructions == MAX_INSTRUCTION:
dbg.single_step(False)
return DBG_CONTINUE
else:
# Disassemble the instruction
current_instruction = dbg.disasm(dbg.context,Eip)
print "#%d\t0x%08x : %s" % (total_instructions, dbg.context.Eip, current_instruction)
total_instructions += 1
dbg.single_step(True)
return DBG_CONTINUE
Discloser: I do not guarantee that the code above will work if copied and pasted. I typed it out and haven't tested it. However, if basic understanding is acquired, the small syntactical error could be easily fixed. I apologize in advanced if I have any. I don't currently have means or time to test it.
I really hope it helps you out.
So I have a small python program that is spread out across a few classes. In my main class, I tell my title screen class to display and then wait for input. If the input it gets is 'q' it calls back to my main class telling it to set it's stop flag to true. Otherwise, it just loops.
This is the callback I give to my title screen:
def quit():
stopped = True
stopped is set to False outside of the callback. The callback is registered fine, and goes off no problem, but it seems to set stopped to true locally in titlescreen, and not in main. I can fix this by creating a class stopFlag and doing the exact same thing, except in the object.
My question is why do I need to make a new class to do this? Is there a way I can set a global flag in main which is just a boolean without making an object out of it? How can I have the callback reference that boolean?
Edit:
I declare stopped like this:
stopped = False
Here is the quit callback register call:
titleScreen.registerCallbackQuit(quit)
Which looks like:
def registerCallbackQuit(self, callback):
self.callbackQuit = callback
And it calls quit if it gets a in the user input.
global stopped would work (probably). People use classes to avoid globals (among other things). If 'stopped' is spread out over many files, you would need to import it.