Search code examples
pythonanacondatelnetlib

Py telnetlib OKI with 2.7 but error under 3.6


My case is similar to connect Google.com by python 'telnetlib'

With python Anaconda 2.7.10 shell I have the blow script that works well:

HOST ="www.google.com"
tn=telnetlib.Telnet(HOST,"80")
tn.write("GET /index.html HTTP/1.1\nHost:"+HOST+"\n\n")
l=tn.read_all()
print(l)

which gives back:

HTTP/1.1 302 Found
Cache-Control: private
Content-Type: text/html; charset=UTF-8
Referrer-Policy: no-referrer
Location: http://www.google.it/index.html?
gfe_rd=cr&dcr=0&ei=A7KiWv_2G6fCXojstrAO
Content-Length: 276
Date: Fri, 09 Mar 2018 16:10:43 GMTenter code here

If I now move to Python Anaconda 3.6.3 the same script as above I have the below error:

Traceback (most recent call last):
File "<ipython-input-4-0f3256299055>", line 3, in <module>
tn.write("GET /index.html HTTP/1.1\nHost:"+HOST+"\n\n")

File "C:\Users\FP\Anaconda3\lib\telnetlib.py", line 287, in write
if IAC in buffer:

TypeError: 'in <string>' requires string as left operand, not bytesenter    code here

Do you have a suggestions for this ? I red some documentation about the telnetlib but so far did not yet come to a solution :-(. Any idea about what I might try to do ?

Thank you so much ! Fabio.


Solution

  • The problem, ultimately, comes down to the difference in how strings are defined in Python 2 and Python 3. If you have never read about this you can look up some material online, for example this. telnetlib works with bytes objects (Telnet generally works with 7-bit ASCII characters), strings (str objects) in Python 3 are text representation without an specific encoding (until you call their .encode() method to convert them to bytes). When you call the .write() method with a regular string, it checks wether it contains telnetlib.IAC, which is the bytes object b'\xff' (255); since the two objects (the argument and telnetlib.IAC) have different types, it fails.

    The fix, obviously, is to use only bytes objects all along (like strings, but prefixed with b):

    HOST = b"www.google.com"
    tn=telnetlib.Telnet(HOST, 80)
    tn.write(b"GET /index.html HTTP/1.1\nHost:"+HOST+b"\n\n")
    l=tn.read_all()
    print(l)
    

    The good thing is, you can also use b-prefixed strings in Python 2 (from Python 2.6), they'll just be regular Python 2 strings, so the code works for both versions. You can also look into tools like 2to3 to make code porting to Python 3 easier (more on the topic here).