PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0

Saturday, May 14, 2022

[FIXED] Why is the output different with Python 2.7 than Python 3.10?

 May 14, 2022     python, python-2.7, python-3.x, ubuntu     No comments   

Issue

$ /usr/bin/python2 simple.py 200 > out2.pbm
$ /opt/src/Python-3.10.1/bin/python3 simple.py 200 > out3.pbm
$ cmp out2.pbm out3.pbm
out2.pbm out3.pbm differ: byte 304, line 3

The python2 output is correct. The python3 output is incorrect.

Here is a correct .pbm output file.

simple.py is

import sys

w = h = x = y = bit_num = 0
byte_acc = 0
i = 0; iterations = 50
limit = 2.0
Zr = Zi = Cr = Ci = Tr = Ti = 0.0

w = int(sys.argv[1])
h = w

sys.stdout.write("P4\n%d %d\n" % (w, h))

for y in range(h):

    for x in range(w):

        Zr = Zi = 0.0 
        Cr = (2.0 * x / w - 1.5); Ci = (2.0 * y / h - 1.0)        
        
        for i in range(iterations):

            Tr = Zr*Zr - Zi*Zi + Cr
            Ti = 2*Zr*Zi + Ci          
            Zr = Tr; Zi = Ti               
            if Zr*Zr+Zi*Zi > limit*limit:
                break
                        
        if Zr*Zr+Zi*Zi > limit*limit: 
            byte_acc = (byte_acc << 1) | 0x00
        else:
            byte_acc = (byte_acc << 1) | 0x01
                
        bit_num += 1         

        if bit_num == 8:
        
            sys.stdout.write(chr(byte_acc))            
            byte_acc = 0
            bit_num = 0

        elif x == w - 1:

            byte_acc = byte_acc << (8-w%8)
            sys.stdout.write(chr(byte_acc))  
            byte_acc = 0
            bit_num = 0

What changed that could cause the different output?


Solution

I can't run this under Python 3.10.1 (Windows, 64-bit):

**Traceback (most recent call last):
  File ... simple.py", line 39, in <module>
    sys.stdout.write(chr(byte_acc))
  File  ... \lib\encodings\cp1252.py", line 19, in encode
    return codecs.charmap_encode(input,self.errors,encoding_table)[0]
UnicodeEncodeError: 'charmap' codec can't encode character '\x80' in position 0: character maps to <undefined>

If I change the 2 instances of chr() to str() (so that it prints out a string representation of the byte's decimal value instead), it produces the same output under 3.10.1 and 2.7.11.

So you're getting burned by whatever default Unicode encoding scheme is used by your Python for sys.stdout under Python 3.

If I set an envar like so (syntax may differ under your OS):

set PYTHONIOENCODING=latin-1

then both Pythons produce the same output using chr().

One way

Here's one way to "fix it":

import sys
from sys import stdout

if hasattr(stdout, "buffer"): # Python >= 3
    def putbyte(b):
        assert 0 <= b < 256
        stdout.buffer.write(bytes([b]))
else: # before Python 3
    def putbyte(b):
        assert 0 <= b < 256
        stdout.write(chr(b))

and then change your code to use putbyte(byte_acc) instead of the current sys.stdout.write(chr(byte_acc)).

That's not quite enough, though. Writing to the internal buffer yourself also makes you responsible for buffer management across uses. After the current

sys.stdout.write("P4\n%d %d\n" % (w, h))

you also need to add

sys.stdout.flush()

to get the output string into the buffer before you add additional output bytes.



Answered By - Tim Peters
Answer Checked By - Gilberto Lyons (PHPFixing Admin)
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Newer Post Older Post Home

0 Comments:

Post a Comment

Note: Only a member of this blog may post a comment.

Total Pageviews

Featured Post

Why Learn PHP Programming

Why Learn PHP Programming A widely-used open source scripting language PHP is one of the most popular programming languages in the world. It...

Subscribe To

Posts
Atom
Posts
Comments
Atom
Comments

Copyright © PHPFixing