473,383 Members | 1,919 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

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

asyncore/asynchat IRC client

6
Hi there guys and girls.

I'm writing an IRC bot (even though there are loads out there that can do what I want, I love to learn-by-doing) and currently use the following to connect to the server:

Expand|Select|Wrap|Line Numbers
  1. import sys, string, os
  2. import socket, asyncore, asynchat
  3. from irc_config import *
  4. from irc_parse import *
  5. from irc_modules import *
  6. #from irc_connect import *
  7.  
  8. # create our socket
  9. sock = socket.socket()
  10.  
  11. # start us up
  12. parser = parse( sock, config.s )
  13.  
  14. # load all our modules
  15. startup_modules( parser )
  16.  
  17. # connect to our server
  18. sock.connect( ( config.s, config.p ) )
  19.  
  20. # our buffer destination
  21. readbuffer = ''
  22.  
  23. # send our initial nick/user bits
  24. sock.send( 'NICK %s\r\n' % config.n )
  25. sock.send( 'USER %s iw 0 :%s\r\n' % ( config.i, config.r ) )
  26.  
  27. # enter our data loop
  28. while 1:
  29.     try:
  30.         bytes_received = readbuffer
  31.  
  32.         while bytes_received >= config.b:
  33.             packet = sock.recv( config.b )
  34.             bytes_received = len( packet )
  35.             readbuffer += packet
  36.  
  37.     except Exception, e:
  38.         if config.b == 1:
  39.             print e
  40.             print '<< DEBUG >> Fatal error.'
  41.         sys.exit(1)
  42.  
  43.     while readbuffer.find( '\r\n' ) >= 0:
  44.         currentline = readbuffer[:readbuffer.find( '\r\n' )]
  45.         readbuffer = readbuffer[len( currentline )+2:]
  46.         print currentline
  47.  
  48.         parser.irc_parse( currentline )
Now, this works - just fine and dandy. However, the birds aren't quite tweeting and I'm not sitting bare arsed on the office photocopier with a party hat on quite yet. No, no. In fact, I realise that this blocking method of reading sucks hard. I have written numerous IRC clients in C before that use select and fifo buffers and I wish to do the same in python.

I am having a very hard time getting my head around even where to start with this - can someone please help with a very simple example that I can butcher to my own evil devices?

Thanks for the help in advance,

Ian
Jul 2 '07 #1
12 6196
bartonc
6,596 Expert 4TB
Hey, Ian. Love the way you write. I've got a USB model that queues read packets for the app to read when it gets around to it around here somewhere. I'll dig up that link for you.

I hope you like our Python forum,
Barton
Jul 2 '07 #2
bartonc
6,596 Expert 4TB
Hey, Ian. Love the way you write. I've got a USB model that queues read packets for the app to read when it gets around to it around here somewhere. I'll dig up that link for you.

I hope you like our Python forum,
Barton
Ah, here it is. Threading and Queuing, all in one.

I haven't used the asyn* modules.
Jul 2 '07 #3
brks
6
Hey, Ian. Love the way you write.
Thank you - I've found over the years that the more entertaining your questions are to read, the more likely people are to read and reply! :o)

Ah, here it is. Threading and Queuing, all in one.

I haven't used the asyn* modules.
Thanks again for that - it was an interesting read. I see the logic behind the threading, almost deamonizing reading and the concept I think it pretty much what I need. However, much to my distress, every current example of python IRC bots manages to utilise asyn* modules in such a way as to completely confuse me and, I personally think, over-complicate the whole thing. I'm pretty sure it should go somewhere along the lines of (mostly from python bot 'phenny'):

Expand|Select|Wrap|Line Numbers
  1. import sys, os, socket, asyncore, asynchat
  2.  
  3. class Bot:
  4.    def __init__(self, nick): 
  5.       asynchat.async_chat.__init__(self)    
  6.       self.buffer = ''
  7.       self.set_terminator('\r\n')
  8.       self.nick = nick
  9.       self.msgstack = []
  10.  
  11.    def write(self, args, text=None): 
  12.       if text is not None: 
  13.          self.push(' '.join(args) + ' :' + text + '\r\n')
  14.       else: self.push(' '.join(args) + '\r\n')
  15.  
  16.    def handle_connect(self): 
  17.       self.write(('NICK', self.nick))
  18.       self.write(('USER', self.uid, '+iw', self.nick), self.name)
  19.  
  20.    def collect_incoming_data(self, data): 
  21.       self.buffer += data
  22.  
  23.    def found_terminator(self): 
  24.       line = self.buffer
  25.       self.buffer = ''
  26.       if line.startswith(':'): 
  27.          origin, line = line[1:].split(' ', 1)
  28.          origin = Origin(origin)
  29.       else: origin = None
  30.  
  31.       if ' :' in line: 
  32.          args, text = line.split(' :', 1)
  33.       else: args, text = line, ''
  34.       args = args.split()
  35.  
  36.       if origin: origin.replyTo(self.nick, args)
  37.       self.dispatch(args, text, origin)
  38.  
  39.    def todo(self, args, *text):
  40.       command = ' '.join(args)
  41.       if text:
  42.           command = '%s : %s' % (command, ' '.join(text))
  43.       command = re.sub(r"\n", "", command)
  44.       command = re.sub(r"\r", "", command)      
  45.       self.push(command + CRLF)
  46.  
  47.    def run(self, host, port): 
  48.       self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
  49.       time.sleep(0.5)
  50.       self.connect((host, port))
  51.       time.sleep(0.5)
  52.       asyncore.loop()
  53.  
  54. test = Bot.run
  55. test( 'irc.some.server.org', 6667 ) # should start the bot off
  56.  
Now that I've pasted nearly all of somebody else's work I guess I should ask a few questions hey!

1) asyncore.loop() - what exactly is that doing? Is that like my initial while 1: loop in my very first post? If so, where is the data read to? self.buffer?

2) does assigning something to self. make it globally available or is it just accessible within that class?

3) can someone explain what 'dispatch' is doing exactly?

I hope you like our Python forum,
Barton
If everyone is as helpful and friendly as yourself I'll be sticking around a lot more!

All the best,

Ian
Jul 3 '07 #4
brks
6
OK - I've finally done it.

After many cups of coffee and a very late night, the problem has been solved and I have asynchronous reading once more. Awesome.

Thanks for your help - I'm sure I'll be sticking around :o)

All the best,

Ian
Jul 3 '07 #5
bartonc
6,596 Expert 4TB
OK - I've finally done it.

After many cups of coffee and a very late night, the problem has been solved and I have asynchronous reading once more. Awesome.

Thanks for your help - I'm sure I'll be sticking around :o)

All the best,

Ian
Any chance that we can get a peek at you work for the benefit of the budding Pythoneers who visit in the future?
Jul 3 '07 #6
brks
6
Sure thing!

Expand|Select|Wrap|Line Numbers
  1. #!/usr/bin/env python
  2.  
  3. import os, sys
  4. import socket, asyncore, asynchat
  5. import irc_config
  6. import irc_parse
  7. import irc_modules
  8.  
  9. class Bot( asynchat.async_chat ):
  10.     def __init__( self, config ):
  11.         asynchat.async_chat.__init__( self )   
  12.         self.buffer = ''
  13.         self.set_terminator( '\r\n' )
  14.         self.nick = config.n
  15.         self.ident = config.i
  16.         self.realname = config.r
  17.         self.debug = config.d
  18.         self.parser = irc_parse.parse_irc_input( config.s, self.write )
  19.  
  20.         # load all our modules
  21.         irc_modules.startup_modules( self.parser )
  22.  
  23.     def write( self, text ):
  24.         if self.debug == 1:
  25.             print '<< DEBUG >> WRITING "%s" TO SOCKET!' % text
  26.         self.push( text + '\r\n' )
  27.  
  28.  
  29.     def handle_connect( self ):
  30.         self.write( 'NICK %s' % self.nick )
  31.         self.write( 'USER %s iw 0 :%s' % ( self.ident, self.realname ) )
  32.  
  33.     def collect_incoming_data( self, data ):
  34.         self.buffer += data
  35.  
  36.     def found_terminator( self ):
  37.         line = self.buffer
  38.         self.buffer = ''
  39.         if self.debug == 1:
  40.             print '<< DEBUG >> %s' % line
  41.         self.parser.parse_text( line )
  42.  
  43.     def run( self, host, port ):
  44.         self.create_socket( socket.AF_INET, socket.SOCK_STREAM )
  45.         self.connect( ( host, port ) )
  46.         asyncore.loop()
  47.  
  48. # attemptfork is thanks to phenny irc bot ( http://inamidst.com/phenny/ )
  49. def attemptfork(): 
  50.     try: 
  51.         pid = os.fork()
  52.         if pid > 0:
  53.             sys.exit( 0 )
  54.     except OSError, e: 
  55.         raise OSError( 'Could not daemonize process: %d ( %s )' % ( e.errno, e.strerror ) )
  56.     os.setsid()
  57.     os.umask( 0 )
  58.     try: 
  59.         pid = os.fork()
  60.         if pid > 0: 
  61.             sys.exit( 0 )
  62.     except OSError, e: 
  63.         raise OSError( 'Could not daemonize process: %d ( %s )' % ( e.errno, e.strerror ) )
  64.  
  65. # load our config
  66. conf = irc_config.config
  67.  
  68. if conf.d == 0 and conf.b == 1 and hasattr( os, 'fork' ): 
  69.     attemptfork()
  70.  
  71. # initialize
  72. mypybot = Bot( conf )
  73.  
  74. # and run
  75. mypybot.run( conf.s, conf.p )
there's a lot left to the imagination, but you see the general jist of what's happening as far as asynchronous data transfer goes!

All the best guys,

Ian
Jul 3 '07 #7
bartonc
6,596 Expert 4TB
Thanks, Ian. Hope to see ya 'round...
Barton
Jul 3 '07 #8
bvdet
2,851 Expert Mod 2GB
Ian,

I appreciate your sharing with us. This is new to me - maybe I can learn something!

BV
Jul 3 '07 #9
brks
6
no problems guys - glad it was so useful

i'll keep you all updated on the architecture i'm releasing as a barse-bones module driven irc bot

if you're a die-hard irc'er like myself then you'll love it!

cheerio

Ian
Jul 3 '07 #10
bartonc
6,596 Expert 4TB
no problems guys - glad it was so useful

i'll keep you all updated on the architecture i'm releasing as a barse-bones module driven irc bot

if you're a die-hard irc'er like myself then you'll love it!

cheerio

Ian
(OK) You meant to say "barse-bones", right? ROFL
Jul 3 '07 #11
brks
6
It was meant to be 'bare-bones' admittedly, but i thought no-one would notice ;)
Jul 4 '07 #12
This looks very interesting. I use irclib.py for my ircbot, but I think I will take a look at this, when you release it, as well.
Jul 5 '07 #13

Sign in to post your reply or Sign up for a free account.

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...
4
by: F.G.Testa | last post by:
Hi! Is there a way to access a specific connected socket when using a derived asyncore.dispatcher and derived asynchat.async_chat? class AcmeServer(asyncore.dispatcher): def __init__(self,...
4
by: Joshua Moore-Oliva | last post by:
Ok.. so here is my situation. I have an application that I would love to be able to use asynchat with for it's handle_close, found_terminator etc abstraction on. However, I must use a separate...
2
by: Dustin | last post by:
I've been trying to create a "byte streaming server", it's basically a chat server, but I'd like to use it for transfering large amounts of data between two connected clients. Sounds simple...
16
by: Rob Snyder | last post by:
Greetings - I've embarked on a small learning project, trying to get a better grasp of the asyncore and asynchat modules. The project involves building a simple instant messenger application for...
0
by: Z. Kotzer | last post by:
I can not get error notifications when an asynchat based client tries to connect to a non-responsive address. To validate the problem I changed lib/test/test_asynchat.py as follows: class...
0
by: David Hirschfield | last post by:
I'm implementing a relatively simple inter-application communication system that uses asyncore/asynchat to send messages back and forth. The messages are prefixed by a length value and terminator...
0
by: Giampaolo Rodola' | last post by:
Hi, I post this message here in the hope someone using asyncore could review this. Since the thing I miss mostly in asyncore is a system for calling a function after a certain amount of time, I...
0
by: davy zhang | last post by:
Python3.0rc1 windowsxp in the lib\asynchat.py def handle_write (self): self.initiate_send() def push (self, data): sabs = self.ac_out_buffer_size if len(data) sabs:
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...
0
by: ryjfgjl | last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...

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.