I've a problem during exception-handling with the imapclient-library.
I tried to handle the LoginError like this:
source = IMAPClient(host=args.source_server, port=args.source_port, ssl=not args.source_no_ssl)
try:
print('Login source...'.format(args.source_user), end='', flush=False)
source.login(args.source_user, args.source_pass)
print('OK')
except exceptions.LoginError as e:
print('ERROR: {}'.format(e))
exit()
In case of exception i've got this:
Login source...ERROR: b'Invalid login'
I think The problem is, that format
is calling the __str__()
-method of the Exception-object and do not try to decode.
So the main question is who can i convert this string
"b'Invalid login'"
to a normal bytes-object like this?
b'Invalid login'
@lenik
If i use e.message.decode()
like this:
try:
print('Login source...'.format(args.source_user), end='', flush=False)
source.login(args.source_user, args.source_pass)
print('OK')
except exceptions.LoginError as e:
print('ERROR: {}'.format(e.message.decode()))
exit()
I've got an AttributeError:
AttributeError: 'LoginError' object has no attribute 'message'
@snakecharmerb
try:
print('Login source...'.format(args.source_user), end='', flush=False)
source.login(args.source_user, args.source_pass)
print('OK')
except exceptions.LoginError as e:
print('ERROR: {}'.format(e.args[0].decode()))
exit()
AttributeError: 'str' object has no attribute 'decode'
imapclient
's login method looks like this:
def login(self, username, password):
"""Login using *username* and *password*, returning the
server response.
"""
try:
rv = self._command_and_check(
'login',
to_unicode(username),
to_unicode(password),
unpack=True,
)
except exceptions.IMAPClientError as e:
raise exceptions.LoginError(str(e))
logger.info('Logged in as %s', username)
return rv
We can see that it calls str
on IMAPClientError
, so if IMAPClientError
was created with a bytes
instance as its argument then we end up with stringified bytes in LoginError
*.
There are two ways to deal with this:
args
tuple:msg = e.args[0].decode()
msg = ast.literal_eval(str(e)).decode()
Of the two approaches, I think (1) is better in this specific case, but (2) is more generally applicable when you have stringified bytes.
*Looking at the history of the imaplib module on github, it looks as if it changed to explicitly decode error messages before raising errors from the authenticate command in Python 3.5. So another solution might be to upgrade to Python 3.5+.