-
-
Notifications
You must be signed in to change notification settings - Fork 29.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
'str' object has no attribute 'more' [/usr/lib/python3.2/asynchat.py|initiate_send|245] #56732
Comments
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: --------------------------------------------------------------- A comment from Stackoverflow on why it happens: --------------------------------------------------------------- def initiate_send(self):
while self.producer_fifo and self.connected:
first = self.producer_fifo[0]
...
try:
data = buffer(first, 0, obs)
except TypeError:
data = first.more() <--- here Seems like somebody put a string in self.producer_fifo instead of an asyncchat.simple_producer, which is the only class in async*.py with a more() method. |
Actually, the error is that in Python 3 you should use bytes objects when transmitting/receiving data over the network, not (unicode) strings. Of course, the error message should be made less obscure. |
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. |
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. |
The part of the code where that is more likely to happen is the push() method. 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): |
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|460] [/home/caelyn/CPython/async_chat_error/Lib/asyncore.py|handle_connect_event|448] [asynchat_example.py|handle_connect|16] [/home/caelyn/CPython/async_chat_error/Lib/asynchat.py|push|185]) Which is, I think, is a bit more useful. |
*will now produce. |
I've no objection to people trying to take this forward but they should be aware that asyncio is recommended for new code. |
We were really looking for your approval, thank you. |
Just close this as asynchat is deprecated from 3.2. |
New changeset f8c9dd2626aa by Victor Stinner in branch '3.4': New changeset 4b29d338cc41 by Victor Stinner in branch 'default': |
I fixed the issue. I copied the check from asyncio, _SelectorSocketTransport.write() of asyncio.selector_events for example. |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: