python 2/3 compatibility issue with exception - python-3.x

I wrote the following code that works with python3
try:
json.loads(text)
except json.decoder.JSONDecodeError:
(exception handling)
However, if I use python2, when json.loads throws the exception I get:
File "mycode.py", line xxx, in function
except json.decoder.JSONDecodeError:
AttributeError: 'module' object has no attribute 'JSONDecodeError'
And actually, https://docs.python.org/2/library/json.html doesn't mention any JSONDecodeError exception, while https://docs.python.org/3/library/json.html does.
How can I have the code running both with python 2 and 3?

In Python 2 json.loads raises ValueError:
Python 2.7.9 (default, Sep 17 2016, 20:26:04)
>>> json.loads('#$')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python2.7/json/__init__.py", line 338, in loads
return _default_decoder.decode(s)
File "/usr/lib/python2.7/json/decoder.py", line 366, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
File "/usr/lib/python2.7/json/decoder.py", line 384, in raw_decode
raise ValueError("No JSON object could be decoded")
ValueError: No JSON object could be decoded
You can try to use json.decoder.JSONDecodeError. If it fails you will know that you need to catch ValueError:
try:
json_parse_exception = json.decoder.JSONDecodeError
except AttributeError: # Python 2
json_parse_exception = ValueError
Then
try:
json.loads(text)
except json_parse_exception:
(exception handling)
Will work in either case.

Related

Error : "Command raised an exception: TypeError: 'NoneType' object is not subscriptable" with function randrange()

I'm currently coding a discord bot, and I have a command that sends the URL of a random anime using a MyAnimeList api. Here is my code :
#client.command()
async def anime(ctx):
await ctx.send("Récupération d'un anime...")
anime = 0
while anime == 0:
async with ctx.typing():
try:
ref = randrange(1, 40500)
anime = Anime(ref)
await ctx.send(anime)
except ValueError as err:
if str(err) == 'No such id on MyAnimeList':
pass
else:
pass
I'm using a while loop to retry if the api returns a 404 error (because not every single anime id is used on myanimelist.net)
The error i'm getting is :
Ignoring exception in command anime:
Traceback (most recent call last):
File "/home/container/.local/lib/python3.6/site-packages/discord/ext/commands/core.py", line 83, in wrapped
ret = await coro(*args, **kwargs)
File "bot.py", line 46, in anime
anime = Anime(ref)
File "/home/container/.local/lib/python3.6/site-packages/mal/anime.py", line 8, in __init__
super().__init__(mal_id, "anime", timeout)
File "/home/container/.local/lib/python3.6/site-packages/mal/mal.py", line 15, in __init__
title = self._page.find("meta", property="og:title")["content"]
TypeError: 'NoneType' object is not subscriptable
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/home/container/.local/lib/python3.6/site-packages/discord/ext/commands/bot.py", line 892, in invoke
await ctx.command.invoke(ctx)
File "/home/container/.local/lib/python3.6/site-packages/discord/ext/commands/core.py", line 797, in invoke
await injected(*ctx.args, **ctx.kwargs)
File "/home/container/.local/lib/python3.6/site-packages/discord/ext/commands/core.py", line 92, in wrapped
raise CommandInvokeError(exc) from exc
discord.ext.commands.errors.CommandInvokeError: Command raised an exception: TypeError: 'NoneType' object is not subscriptable
I think that the problem comes from the fonction randrange(). When i was looking for a solution, every single person with the same issue had a code that was involving lists, but I don't have any in my code...
I'm using Python 3.7.6.
The problem probably comes from the mal-api library itself...
You might be running into rate limiting or something else that is interfering with the web pages you're getting back. You could try writing a wrapper class around Anime to look at the _page attribute to see what the problem is:
class MyAnime(Anime):
def __init__(self, ref):
try:
super().__init__(ref)
except:
print(self._page)
print(self._page.find("meta"))
print(self._page.find("meta", property="og:title"))

A bytes-like object is required, not 'str' (not sending to dataOutput)

I have been automating some, and got a problem when migrating from 2.7 to 3.7. The code is as shown
def writeDataToOutput(dataOutput):
global myUartPort
global mySocket
if (m_UseRTT):
try:
mySocket.sendall(dataOutput)
except socket.error:
print('Send failed')
else:
myUartPort.write(dataOutput)
And when running i get this error message
Traceback (most recent call last):
File "monkeytest.py", line 1324, in <module>
executeScript()
File "monkeytest.py", line 1255, in executeScript
if executeCommandLine(line) == 0:
File "monkeytest.py", line 1159, in executeCommandLine
executeCommand(commandPayload, 1, 1)
File "monkeytest.py", line 587, in executeCommand
writeDataToOutput(command + "\r\n")
File "monkeytest.py", line 309, in writeDataToOutput
mySocket.sendall(dataOutput)
TypeError: a bytes-like object is required, not 'str'
I cannot see the wrong in my method, I have tried sendto() without any success.

Issue with python3 bot: ValueError: invalid literal for int() with base 10: ''

When running a python3 bot im getting the following error:
ValueError: invalid literal for int() with base 10: ''
Been looking through main.py to try and see where the problem is coming from with no luck. I'll admit i'm lacking experience and just trying to learn some new things, any help would be appreciated.
Below is the error:
wirng#localhost:~/bot# python3 main.py
Traceback (most recent call last):
File "main.py", line 1133, in <module>
client = BotClient(max_messages=10)
File "main.py", line 274, in __init__
self.config = Config()
File "main.py", line 133, in __init__
self.patreon_server = int(config.get('DEFAULT', 'patreon_server'))
ValueError: invalid literal for int() with base 10: ''
Im unsure where the error is coming from but i think its from this part of the code:
self.patreon = config.get('DEFAULT', 'patreon_enabled') == 'yes'
self.patreon_server = int(config.get('DEFAULT', 'patreon_server'))
if self.patreon:
logger.info('Patreon is enabled. Will look for servers {}'.format(self.patreon_server))

Python Multiprocessing( TypeError: cannot serialize '_io.BufferedReader' object )

I'm trying to make dictionary attack on zip file using Pool to increase speed.
But I face next error in Python 3.6, while it works in Python 2.7:
Traceback (most recent call last):
File "zip_crack.py", line 42, in <module>
main()
File "zip_crack.py", line 28, in main
for result in results:
File "/usr/lib/python3.6/multiprocessing/pool.py", line 761, in next
raise value
File "/usr/lib/python3.6/multiprocessing/pool.py", line 450, in _ handle_tasks
put(task)
File "/usr/lib/python3.6/multiprocessing/connection.py", line 206, in send
self._send_bytes(_ForkingPickler.dumps(obj))
File "/usr/lib/python3.6/multiprocessing/reduction.py", line 51, in dumps
cls(buf, protocol).dump(obj)
TypeError: cannot serialize '_io.BufferedReader' object
I tried to search for same errors but couldn't find answer that can help here.
Code looks like this
def crack(pwd, f):
try:
key = pwd.strip()
f.extractall(pwd=key)
return True
except:
pass
z_file = zipfile.ZipFile("../folder.zip")
with open('words.dic', 'r') as passes:
start = time.time()
lines = passes.readlines()
pool = Pool(50)
results = pool.imap_unordered(partial(crack, f=z_file), lines)
pool.close()
for result in results:
if result:
pool.terminate()
break
pool.join()
I also tried another approach using map
with contextlib.closing(Pool(50)) as pool:
pool.map(partial(crack, f=z_file), lines)
which worked great and found passwords quickly in Python 2.7 but it throws same exception in python 3.6

New line on error message in KeyError - Python 3.3

I am using Python 3.3 through the IDLE. While running a code that looks like:
raise KeyError('This is a \n Line break')
it outputs:
Traceback (most recent call last):
File "test.py", line 4, in <module>
raise KeyError('This is a \n Line break')
KeyError: 'This is a \n Line break'
I would like it to output the message with the line break like this:
This is a
Line Break
I have tried to convert it to a string before or using os.linesep but nothing seems to work. Is there any way I can force the message to be correctly shown on the IDLE?
If I raise an Exception (instead of KeyError) then the output is what I want, but I would like to still raise a KeyError if possible.
You problem has nothing to do with IDLE. The behavior you see is all from Python. Running current repository CPython interactively, from a command line, we see the behavior you reported.
Python 3.7.0a2+ (heads/pr_3947:01eae2f721, Oct 22 2017, 14:06:43)
[MSC v.1900 32 bit (Intel)] on win32
>>> raise KeyError('This is a \n Line break')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'This is a \n Line break'
>>> s = 'This is a \n Line break'
>>> s
'This is a \n Line break'
>>> print(s)
This is a
Line break
>>> raise Exception('This is a \n Line break')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
Exception: This is a
Line break
>>> raise IndexError(s)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: This is a
Line break
>>> try:
... raise KeyError('This is a \n Line break')
... except KeyError as e:
... print(e)
'This is a \n Line break'
>>> try:
... raise KeyError('This is a \n Line break')
... except KeyError as e:
... print(e.args[0])
This is a
Line break
I don't know why KeyError acts differently from even IndexError, but printing e.args[0] should work for all exceptions.
EDIT
The reason for the difference is given in this old tracker issue, which quotes a comment in the KeyError source code:
/* If args is a tuple of exactly one item, apply repr to args[0].
This is done so that e.g. the exception raised by {}[''] prints
KeyError: ''
rather than the confusing
KeyError
alone. The downside is that if KeyError is raised with an
explanatory
string, that string will be displayed in quotes. Too bad.
If args is anything else, use the default BaseException__str__().
*/
This section appears in the KeyError_str object definition in Objects/exceptions.c of the Python source code.
I will mention your issue as another manifestation of this difference.
There is a way to get the behavior you want: Simply subclass str and override __repr__:
class KeyErrorMessage(str):
def __repr__(self): return str(self)
msg = KeyErrorMessage('Newline\nin\nkey\nerror')
raise KeyError(msg)
Prints:
Traceback (most recent call last):
...
File "", line 5, in
raise KeyError(msg)
KeyError: Newline
in
key
error

Resources