Search code examples
pythonpython-3.xstringiopython-2to3

Error Remains After Running 2to3.py on a Module


I used the 2to3.py script to convert several of my files to Python 3 a while back. I believe I need to run all fixers, so my command included

-f all -f buffer -f idioms -f set_literal -f ws_comma -w

I tried to run my converted code with Python 3, but got an error

[Errno 22] Invalid argument

on the line

stream.seek(-2,1)

stream is a StringIO object that is being used to parse a file. Is this a known difference in Python 2 and 3, so should I use different methods/syntax? Or is the issue in the 2to3 conversion - perhaps I didn't run the tool correctly. (I mean to run as many fixers as possible)


Solution

  • I don't know for sure, but I'm guessing this is a casualty of the new Unicode handling in 3.x:

    In [3]: file_ = open('/etc/services', 'r')
    
    In [4]: file_.readline()
    Out[4]: '# Network services, Internet style\n'
    
    In [5]: file_.readline()
    Out[5]: '#\n'
    
    In [6]: file_.readline()
    Out[6]: '# Note that it is presently the policy of IANA to assign a single well-known\n'
    
    In [7]: file_.seek(-2, 1)
    ---------------------------------------------------------------------------
    UnsupportedOperation                      Traceback (most recent call last)
    <ipython-input-7-6122ef700637> in <module>()
    ----> 1 file_.seek(-2, 1)
    
    UnsupportedOperation: can't do nonzero cur-relative seeks
    

    However, you can use binary I/O to do this:

    In [9]: file_ = open('/etc/services', 'rb')
    
    In [10]: file_.readline()
    Out[10]: b'# Network services, Internet style\n'
    
    In [11]: file_.readline()
    Out[11]: b'#\n'
    
    In [12]: file_.readline()
    Out[12]: b'# Note that it is presently the policy of IANA to assign a single well-known\n'
    
    In [13]: file_.seek(-2, 1)
    Out[13]: 112
    

    BTW, 3to2 is more effective than 2to3 if you want to maintain a dual codebase for a while. Also, many people (including me) are having luck maintaining a single codebase that runs on 2.x and 3.x, rather than using 2to3 or 3to2.

    Here's a link to a presentation I gave about writing code to run on 2.x and 3.x: http://stromberg.dnsalias.org/~dstromberg/Intro-to-Python/

    PS: Analogous to StringIO, is BytesIO:

    In [17]: file_ = io.BytesIO(b'abc def\nghi jkl\nmno pqr\n')
    
    In [18]: file_.readline()
    Out[18]: b'abc def\n'
    
    In [19]: file_.seek(-2, 1)
    Out[19]: 6