According to poplib.error_proto
documentation:
Exception raised on any errors from this module (errors from socket module are not caught). The reason for the exception is passed to the constructor as a string.
So, you don't need to decode it.
UPDATE It seems like the documentation does not match the actual implementation.
You can access the arguments passed to the exception constructor using args
attribute.
p = poplib.POP3('mail.site.com')
try:
p.user('skillian@site.com')
p.pass_('badpassword')
except poplib.error_proto as e:
print(e.args[0].decode('ascii')) # `'ascii'` is not necessary.