msg140073 - (view) |
Author: Gryllida (Gryllida) |
Date: 2011-07-10 00:04 |
Asynchat push() function has a bug which prevents it from functioning. This code worked fine with Python 2. --------------------------------------------------------------- # https://github.com/jstoker/BasicBot import asynchat,asyncore,socket class asynchat_bot(asynchat.async_chat): def __init__(self, host, port): asynchat.async_chat.__init__(self) self.create_socket(socket.AF_INET,socket.SOCK_STREAM) self.set_terminator('\r\n') self.data='' self.remote=(host,port) self.connect(self.remote) def handle_connect(self): self.push('USER BasicBot 8 %s :BasicBot! http://github.com/jstoker/BasicBot\r\nNICK testbot\r\n' % self.remote[0]) def get_data(self): r=self.data self.data='' return r def collect_incoming_data(self, data): self.data+=data def found_terminator(self): data=self.get_data() if data[:4] == 'PING': self.push('PONG %s' % data[5:]+'\r\n') if '001' in data: self.push('JOIN #bots\r\n') if '~hi' in data: self.push('PRIVMSG #bots :hi.\r\n') if __name__ == '__main__': asynchat_bot('127.0.0.1',16667) asyncore.loop() --------------------------------------------------------------- In Python 3 however, the exception follows: --------------------------------------------------------------- ~/tests/BasicBot$ python3 asynchat_bot.py error: uncaptured python exception, closing channel <__main__.asynchat_bot connected at 0xb70078ac> (<class 'AttributeError'>:'str' object has no attribute 'more' [/usr/lib/python3.2/asyncore.py|write |
89] [/usr/lib/python3.2/asyncore.py |
handle_write_event |
msg140104 - (view) |
Author: Antoine Pitrou (pitrou) *  |
Date: 2011-07-11 09:44 |
Actually, the error is that in Python 3 you should use bytes objects when transmitting/receiving data over the network, not (unicode) strings. That is, replace '\r\n' with b'\r\n', etc. Of course, the error message should be made less obscure. |
|
|
msg216471 - (view) |
Author: Caelyn McAulay (math_foo) |
Date: 2014-04-16 14:19 |
Here is a small script that runs fine under 2.7 but demonstrates the error when run at 3.5. If, at all the points annotated with '#not bytes :-(', the unicode strings are replaced with bytes objects, the example then successfully runs at 3.5. |
|
|
msg216485 - (view) |
Author: Caelyn McAulay (math_foo) |
Date: 2014-04-16 16:08 |
I was unable to locate a point in the code where we could be certain that the error was ultimately caused by trying to use (unicode) strings instead of bytes object. The patch adds a logging statement suggesting what the trouble is when the error is (probably) encountered. Someone with more experience than me will need to make the call about whether this is a useful addition or not. |
|
|
msg216549 - (view) |
Author: Giampaolo Rodola' (giampaolo.rodola) *  |
Date: 2014-04-16 18:42 |
The part of the code where that is more likely to happen is the push() method. One might also submit a producer (push_with_producer()) erroneously returning strings on more() though; how to properly fix this one is not clear to me because of the bad asynchat design. I'd be for simply raising an exception in push() as in: diff --git a/Lib/asynchat.py b/Lib/asynchat.py --- a/Lib/asynchat.py +++ b/Lib/asynchat.py @@ -181,6 +181,8 @@ self.close() def push (self, data): + if not isinstance(data, bytes): + raise TypeError("data must be a bytes object") sabs = self.ac_out_buffer_size if len(data) > sabs: for i in range(0, len(data), sabs): |
|
|
msg216560 - (view) |
Author: Caelyn McAulay (math_foo) |
Date: 2014-04-16 19:18 |
I like that approach decidedly more than my original one. Suggested revision patch attached. The sample script will not produce the following: error: uncaptured python exception, closing channel <__main__.fake_asynchat 127.0.0.1:8000 at 0x7f10a85b4ae8> (<class 'TypeError'>:data must be a bytes object [/home/caelyn/CPython/async_chat_error/Lib/asyncore.py|write |
91] [/home/caelyn/CPython/async_chat_error/Lib/asyncore.py |
handle_write_event |
msg216561 - (view) |
Author: Caelyn McAulay (math_foo) |
Date: 2014-04-16 19:20 |
*will now produce. |
|
|
msg222376 - (view) |
Author: Mark Lawrence (BreamoreBoy) * |
Date: 2014-07-05 21:58 |
I've no objection to people trying to take this forward but they should be aware that asyncio is recommended for new code. |
|
|
msg222388 - (view) |
Author: Antoine Pitrou (pitrou) *  |
Date: 2014-07-06 01:20 |
> I've no objection to people trying to take this forward We were really looking for your approval, thank you. |
|
|
msg222401 - (view) |
Author: Mark Lawrence (BreamoreBoy) * |
Date: 2014-07-06 10:51 |
Just close this as asynchat is deprecated from 3.2. |
|
|
msg222525 - (view) |
Author: Roundup Robot (python-dev)  |
Date: 2014-07-07 22:01 |
New changeset f8c9dd2626aa by Victor Stinner in branch '3.4': Issue [#12523](issue12523 "[closed] 'str' object has no attribute 'more' [/usr/lib/python3.2/asynchat.py|initiate_send |
245]"): asynchat.async_chat.push() now raises a TypeError if it doesn't http://hg.python.org/cpython/rev/f8c9dd2626aa New changeset 4b29d338cc41 by Victor Stinner in branch 'default': (Merge 3.4) Issue [#12523](issue12523 "[closed] 'str' object has no attribute 'more' [/usr/lib/python3.2/asynchat.py |
initiate_send |
msg222526 - (view) |
Author: STINNER Victor (vstinner) *  |
Date: 2014-07-07 22:07 |
I fixed the issue. I copied the check from asyncio, _SelectorSocketTransport.write() of asyncio.selector_events for example. |
|
|