472,980 Members | 2,049 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 472,980 software developers and data experts.

Modification to asyncore.py to support threaded event loop

This is for folks who are familiar with asynchronous event handling in
Python using the asyncore module.

If you have ever used the asyncore module, you will realize that it's
event loop does not have a programmable exit condition. It keeps
looping till the channels in its socket map (a dictionary) are closed
and don't have any pending reads/writes.

If you are using Python threads in your application, by using either
the threading or thread modules, adding asyncore capability on top of
it is a bit tricky. The moment you call asyncore.loop after
initializing your asyncore based client/server, it takes over the main
thread. Hence, if you want to mix threaded classes (derived from
threading.Thread) and asyncore in one program, the only recourse is to
create and initialize all your thread objects first and call
asyncore.loop as the last function in your main thread.

However, with a small hack it is possible to get asyncore event loop
running in its own thread, as shown below.

The following is a mixin class, which derives from threading.Thread
and also overrides asyncore.loop in its 'run()' method.

-================================================== ========================-
import threading

class AsyncoreThread(threading.Thread):
""" Asyncore thread class """

def __init__(self, timeout=30.0, use_poll=0,map=None):
self.flag=True
self.timeout=30.0
self.use_poll=use_poll
self.map=map
threading.Thread.__init__(self, None, None, 'asyncore thread')

def run(self):

self.loop()

def loop(self):

# print 'In AsyncoreThread:loop...'
if self.map is None:
self.map = asyncore.socket_map

if self.use_poll:
if hasattr(select, 'poll'):
poll_fun = asyncore.poll3
else:
poll_fun = asyncore.poll2
else:
# print 'Using asyncore.poll...'
poll_fun=asyncore.poll

while self.map and self.flag:
poll_fun(self.timeout,self.map)

def end(self):
print 'Ending asyncore loop...'
self.flag=False
self.map=None

-================================================== ==========================-
Now you can initialize your asyncore based clients/servers and instead
of calling 'asyncore.loop', do it as follows,

t=AsyncoreThread(timeout=mytimeout,...)
t.start()

Since the 'run()' method of this class calls 'loop()' which is exactly
the same as asyncore.loop, only that it gets the asyncore event
handler running in a separate thread, without monopolizing the main
thread of your Python app.

I have used this model successfully in my program, HarvestMan. I wrote
to Sam Rushing, author of asyncore module and here is what he said.

<QUOTE>
"I would recommend separating out your event loop and sending it to
the
Python folks for possible inclusion in the asyncore module. I had
always intended the loop() function in asyncore.py to be a 'field
replaceable item', and in fact have over the years made many different
versions of it. Though this isn't really talked about in asyncore.py,
it's clear if you look at Medusa, which is where the module came
from."
</QUOTE>

Perhaps this is worth a PEP for inclusion in Python 2.4?

Thanks & Regards

-Anand
Jul 18 '05 #1
3 5194

ab******@gmail.com (Anand Pillai) wrote:

If you have ever used the asyncore module, you will realize that it's
event loop does not have a programmable exit condition. It keeps
looping till the channels in its socket map (a dictionary) are closed
and don't have any pending reads/writes.
With the asyncore that will be included with Python 2.4, loop() has a
'count' argument. Your 'programmable exit condition' is simple...

while not exit_condition_satisfied:
asyncore.loop(count=1)

If you are using Python threads in your application, by using either
the threading or thread modules, adding asyncore capability on top of
it is a bit tricky. The moment you call asyncore.loop after
initializing your asyncore based client/server, it takes over the main
thread. Hence, if you want to mix threaded classes (derived from
threading.Thread) and asyncore in one program, the only recourse is to
create and initialize all your thread objects first and call
asyncore.loop as the last function in your main thread.

However, with a small hack it is possible to get asyncore event loop
running in its own thread, as shown below.
Here's an easier way to get asyncore running in its own thread, with
nearly all the functionality you mention, without having to subclass
Thread.

def asyncore_loop(exit_condition, timeout=30.0,
use_poll=False, map=None):
if map is None:
map = asyncore.map
while map and not exit_condition:
asyncore.loop(timeout=30.0, use_poll=False, map=map, count=1)

exit_condition = []

threading.Thread(target=asyncore_loop, args=(exit_condition,)).start()

#to kill the thread...
exit_condition.append(None)

The following is a mixin class, which derives from threading.Thread
and also overrides asyncore.loop in its 'run()' method.
[snip unnecessary code]
Now you can initialize your asyncore based clients/servers and instead
of calling 'asyncore.loop', do it as follows,
See the snippet I provide above.

Perhaps this is worth a PEP for inclusion in Python 2.4?


Module and/or functionality additions do not require a PEP (from what I
understand). Changing the behavior of the language, adding a builtin,
etc., that requires a PEP.

It is not going to make it into Python 2.4. How would I know this?
Because "no new functionality after the beta". We're on beta 2, and
even small functionality additions that were pre-approved (but not
implemented) are not making it into 2.4.

What about for Python 2.5? I doubt it would be added there either. The
functionality is very simple to implement if you know what you are doing,
and doesn't require copying the internals of asyncore.loop to make it
happen.

- Josiah

Jul 18 '05 #2
I tried your code and this is the result...
Exception in thread Thread-1:
Traceback (most recent call last):
File "/usr/lib/python2.3/threading.py", line 436, in __bootstrap
self.run()
File "/usr/lib/python2.3/threading.py", line 416, in run
self.__target(*self.__args, **self.__kwargs)
File "urlserver.py", line 205, in asyncore_loop
map = asyncore.map
AttributeError: 'module' object has no attribute 'map'

asyncore does not have an attribute named 'map', only socket_map.
'map' is an argument to ascynore.loop function, again not its
attribute.

Did you try this code out before posting it here?

Also, asyncore.loop has a while loop inside it, and you are adding
another while loop on top. Clearly your exit condition, if it works is
going to only exit the outer while loop, not the inner one. I dont
think it is going to work.
-Anand

Josiah Carlson <jc******@uci.edu> wrote in message news:<ma**************************************@pyt hon.org>...
ab******@gmail.com (Anand Pillai) wrote:

If you have ever used the asyncore module, you will realize that it's
event loop does not have a programmable exit condition. It keeps
looping till the channels in its socket map (a dictionary) are closed
and don't have any pending reads/writes.


With the asyncore that will be included with Python 2.4, loop() has a
'count' argument. Your 'programmable exit condition' is simple...

while not exit_condition_satisfied:
asyncore.loop(count=1)

If you are using Python threads in your application, by using either
the threading or thread modules, adding asyncore capability on top of
it is a bit tricky. The moment you call asyncore.loop after
initializing your asyncore based client/server, it takes over the main
thread. Hence, if you want to mix threaded classes (derived from
threading.Thread) and asyncore in one program, the only recourse is to
create and initialize all your thread objects first and call
asyncore.loop as the last function in your main thread.

However, with a small hack it is possible to get asyncore event loop
running in its own thread, as shown below.


Here's an easier way to get asyncore running in its own thread, with
nearly all the functionality you mention, without having to subclass
Thread.

def asyncore_loop(exit_condition, timeout=30.0,
use_poll=False, map=None):
if map is None:
map = asyncore.map
while map and not exit_condition:
asyncore.loop(timeout=30.0, use_poll=False, map=map, count=1)

exit_condition = []

threading.Thread(target=asyncore_loop, args=(exit_condition,)).start()

#to kill the thread...
exit_condition.append(None)

The following is a mixin class, which derives from threading.Thread
and also overrides asyncore.loop in its 'run()' method.


[snip unnecessary code]
Now you can initialize your asyncore based clients/servers and instead
of calling 'asyncore.loop', do it as follows,


See the snippet I provide above.

Perhaps this is worth a PEP for inclusion in Python 2.4?


Module and/or functionality additions do not require a PEP (from what I
understand). Changing the behavior of the language, adding a builtin,
etc., that requires a PEP.

It is not going to make it into Python 2.4. How would I know this?
Because "no new functionality after the beta". We're on beta 2, and
even small functionality additions that were pre-approved (but not
implemented) are not making it into 2.4.

What about for Python 2.5? I doubt it would be added there either. The
functionality is very simple to implement if you know what you are doing,
and doesn't require copying the internals of asyncore.loop to make it
happen.

- Josiah

Jul 18 '05 #3

ab******@gmail.com (Anand Pillai) wrote:

I tried your code and this is the result...
[snip exception]
asyncore does not have an attribute named 'map', only socket_map.
'map' is an argument to ascynore.loop function, again not its
attribute.
socket_map then, whatever.

Did you try this code out before posting it here?
No, I typed it out in my email client. But my statement still holds,
the functionality is trivial to implement if you know what you are doing,
and shouldn't be in the asyncore module.

Also, asyncore.loop has a while loop inside it, and you are adding
another while loop on top. Clearly your exit condition, if it works is
going to only exit the outer while loop, not the inner one. I dont
think it is going to work.


If you check the source code for asyncore.py in Python 2.4 (available
from Python CVS), you will discover that you can provide an optional
'count' argument to asyncore.loop. You'll notice that I both mention
it:
With the asyncore that will be included with Python 2.4, loop() has a
'count' argument. Your 'programmable exit condition' is simple...
and use it:
asyncore.loop(timeout=30.0, use_poll=False, map=map, count=1)


In this case, the 'inner loop' only runs for one pass. Certainly in
Python <2.4, it would run without stopping (unless the socket map became
empty), but I was referencing 2.4, not 2.3 or prior.
- Josiah

Jul 18 '05 #4

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
by: Michael Welsh | last post by:
In order to learn sockets in Python I am trying to write a simple group chat server and client. I need a little nudge, please. My question contains some GUI but only as decoration. The root...
5
by: David M. Wilson | last post by:
Hi peeps, I finally got around recently to doing something serious using Python for serving network clients asynchronously, deciding on asyncore as my starting point. After 2 days or so of...
0
by: Tony Meyer | last post by:
Changes in asyncore from 2.3 to 2.4 mean that asyncore.poll() now passes all the sockets in the map to select.select() to be checked for errors, which is probably a good thing. If an error occurs,...
29
by: Frank Millman | last post by:
Hi all I am writing a multi-user accounting/business system. Data is stored in a database (PostgreSQL on Linux, SQL Server on Windows). I have written a Python program to run on the client,...
3
by: Jos | last post by:
Hello. I'm using the asyncore and _chat modules to create a network server. I also have, running in a separate thread(s), a "producer" which needs to "push" data onto the network connection(s)....
1
by: Chris | last post by:
I've implemented a real basic IRC client class in 100 lines using asynchat (yes I know about Twisted). The problem I'm having is arbitrarily starting and stopping multiple instances of this class...
5
by: JamesHoward | last post by:
I have a problem with python's asyncore module throwing a bad file descriptor error. The code might be difficult to copy here, but the problem is essentially: The server wants to sever the...
7
by: billie | last post by:
Hi all. I've just terminated a server application using asyncore / asynchat frameworks. I wrote a test script that performs a lot of connections to the server app and I discovered that asyncore...
8
by: Frank Millman | last post by:
Hi all I have been using my own home-brewed client/server technique for a while, using socket and select. It seems to work ok. The server can handle multiple clients. It does this by creating a...
0
by: lllomh | last post by:
Define the method first this.state = { buttonBackgroundColor: 'green', isBlinking: false, // A new status is added to identify whether the button is blinking or not } autoStart=()=>{
2
by: DJRhino | last post by:
Was curious if anyone else was having this same issue or not.... I was just Up/Down graded to windows 11 and now my access combo boxes are not acting right. With win 10 I could start typing...
2
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 4 Oct 2023 starting at 18:00 UK time (6PM UTC+1) and finishing at about 19:15 (7.15PM) The start time is equivalent to 19:00 (7PM) in Central...
0
tracyyun
by: tracyyun | last post by:
Hello everyone, I have a question and would like some advice on network connectivity. I have one computer connected to my router via WiFi, but I have two other computers that I want to be able to...
4
NeoPa
by: NeoPa | last post by:
Hello everyone. I find myself stuck trying to find the VBA way to get Access to create a PDF of the currently-selected (and open) object (Form or Report). I know it can be done by selecting :...
3
NeoPa
by: NeoPa | last post by:
Introduction For this article I'll be using a very simple database which has Form (clsForm) & Report (clsReport) classes that simply handle making the calling Form invisible until the Form, or all...
1
by: Teri B | last post by:
Hi, I have created a sub-form Roles. In my course form the user selects the roles assigned to the course. 0ne-to-many. One course many roles. Then I created a report based on the Course form and...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 1 Nov 2023 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM) Please note that the UK and Europe revert to winter time on...
0
NeoPa
by: NeoPa | last post by:
Introduction For this article I'll be focusing on the Report (clsReport) class. This simply handles making the calling Form invisible until all of the Reports opened by it have been closed, when it...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.