Why is the output different in PyScripter console?

362 views Asked by At

From PyScripter (3.6.4.0) REPL console:

*** Python 3.7.7 (tags/v3.7.7:d7c567b08f, Mar 10 2020, 10:41:24) [MSC v.1900 64 bit (AMD64)] on win32. ***
*** Remote Python engine is active ***
>>> d = {}
>>> d['B'] = 12
>>> d['A'] = 10
>>> d['C'] = 34
>>> d
{'A': 10, 'B': 12, 'C': 34}

That result makes us believe that Python sorts the key and doesn't preserve insertion order, whereas it's guaranteed from version 3.6.

Now let's run the exact same version of Python in a console, outside PyScripter:

Python 3.7.7 (tags/v3.7.7:d7c567b08f, Mar 10 2020, 10:41:24) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> d = {}
>>> d['B'] = 12
>>> d['A'] = 10
>>> d['C'] = 34
>>> d
{'B': 12, 'A': 10, 'C': 34}

Insertion order is preserved all right.

Why are the outputs different?

2

There are 2 answers

0
Martijn Pieters On BEST ANSWER

You need to disable the Pretty print output option in pyscripter:

If checked the standard python module pprint is used to format interpreter output.

Find it under Options > IDE Options > Python Interpreter.

The pprint module outputs dictionaries in sorted key order, ignoring the current ordering of the dictionary. From the documentation:

Dictionaries are sorted by key before the display is computed.

It’s not a hack to match older Python version output, because before Python 3.6 the order depended on insertion and deletion order plus a randomised hash seed.

Instead, using pprint gives you nicer output when the output would otherwise become unwieldy, by using newlines and indentation, where the standard representation would just put everything on a single line.

Your specific example doesn't really bring out the difference, a longer dictionary would make it clearer:

>>> from requests import get
>>> from secrets import token_hex
>>> from pprint import pprint
>>> fortunes = {token_hex(4): get("https://fortuneapi.herokuapp.com/").text for _ in range(5)}
>>> print(repr(fortunes))  # standard REPL output prints the repr() result
{'a33435f0': '"If reporters don\'t know that truth is plural, they ought to be lawyers.\\n\\t\\t-- Tom Wicker\\n"\n', '1f08db3c': '"Very few profundities can be expressed in less than 80 characters.\\n"\n', '6037e01e': '"The main problem I have with cats is, they\'re not dogs.\\n\\t\\t-- Kevin Cowherd\\n"\n', 'b817eaf8': '"New York now leads the world\'s great cities in the number of people around\\nwhom you shouldn\'t make a sudden move.\\n\\t\\t-- David Letterman\\n"\n', 'c89994e7': '"I\'m GLAD I remembered to XEROX all my UNDERSHIRTS!!\\n"\n'}
>>> pprint(fortunes)  # pprint outputs pretty-printed lines, sorted.
{'1f08db3c': '"Very few profundities can be expressed in less than 80 '
             'characters.\\n"\n',
 '6037e01e': '"The main problem I have with cats is, they\'re not '
             'dogs.\\n\\t\\t-- Kevin Cowherd\\n"\n',
 'a33435f0': '"If reporters don\'t know that truth is plural, they ought to be '
             'lawyers.\\n\\t\\t-- Tom Wicker\\n"\n',
 'b817eaf8': '"New York now leads the world\'s great cities in the number of '
             "people around\\nwhom you shouldn't make a sudden "
             'move.\\n\\t\\t-- David Letterman\\n"\n',
 'c89994e7': '"I\'m GLAD I remembered to XEROX all my UNDERSHIRTS!!\\n"\n'}

If you only occasionally need to check the specific item order of a dictionary, you could just leave the option enabled, and use print(dictionary) for those exceptional times.

You could also pass the sort_dicts=False argument to pprint(), provided you call it manually; the pprint.pp() function even makes this the default:

>>> from pprint import pp
>>> pp(fortunes)
{'a33435f0': '"If reporters don\'t know that truth is plural, they ought to be '
             'lawyers.\\n\\t\\t-- Tom Wicker\\n"\n',
 '1f08db3c': '"Very few profundities can be expressed in less than 80 '
             'characters.\\n"\n',
 '6037e01e': '"The main problem I have with cats is, they\'re not '
             'dogs.\\n\\t\\t-- Kevin Cowherd\\n"\n',
 'b817eaf8': '"New York now leads the world\'s great cities in the number of '
             "people around\\nwhom you shouldn't make a sudden "
             'move.\\n\\t\\t-- David Letterman\\n"\n',
 'c89994e7': '"I\'m GLAD I remembered to XEROX all my UNDERSHIRTS!!\\n"\n'
}

Or you could ask the PyScripter project to use that option in their console implementation.

0
Jean-François Fabre On

In pyscripter REPL I get the correct result when I don't rely on the REPL to provide the answer but use a print statement:

>>> print(d)
{'B': 12, 'A': 10, 'C': 34}

where just d yields the keys as if they were sorted:

>>> d
{'A': 10, 'B': 12, 'C': 34}

So don't trust pyscripter REPL output when it comes to dictionary order.