3

Is there a way to make python2 scripts compatible with python3 with telnetlib?

I noticed that I need to prefix read_until() with the letter b, and I need to use encode('ascii') on the string when I want to write().

Python2

tn = telnetlib.Telnet("192.168.1.45")
tn.write("ls " + dirname + "\n")
answer = tn.read_until(":/$")

Python3

tn = telnetlib.Telnet("192.168.1.45")
cmd_str = "ls " + dirname + "\n"
tn.write(cmd_str.encode('ascii'))
answer = tn.read_until(b":/$")

This would help me update many scripts to 3.x as it the only major change.

Thanks!

ForeverLearning
  • 413
  • 5
  • 25
  • 1
    The purpose of this change and many like it in python 3 is to force you to make a distinction between strings and encoded bytes – in fact the whole reason Python 3 got a new version number (rather than being "Python 2.8") was because of this change. So there is no simple switch that will make the telnet module accept unencoded strings. What is your goal exactly? Minimise work updating an old code base? Do you want it to support Python 2 and 3 at once? – Arthur Tacca Feb 11 '20 at 20:26
  • Thanks for this explanation! Yes, I want to minimize work on an existing set of old scripts (post updated). – ForeverLearning Feb 11 '20 at 21:28

2 Answers2

2

You could write your own subclass in encodingtelnetlib.py

class Telnet(Telnet):

    def __init__(self, host=None, port=0,
                 timeout=socket._GLOBAL_DEFAULT_TIMEOUT,
                 encoding='ascii'):
         self.encoding = encoding
         super().__init__(host, port, timeout)

    def write(self, buffer):
        if isinstance(buffer, str):
            buffer = buffer.encode(self.encoding)
        return super().write(buffer)

    # and etc.... for other methods

Now its a question of changing import telnetlib to import encodingtelnetlib as telnetlib. That's easier than finding every read and write.

Arthur Tacca
  • 8,833
  • 2
  • 31
  • 49
tdelaney
  • 73,364
  • 6
  • 83
  • 116
0

Probably not as Python3 uses utf-8 encoding by default while Python2 used ascii. Therefore if you need an ascii encoded string you need to manually change the encoding.

Jakob F
  • 1,046
  • 10
  • 23
  • The default encoding in python 3 just affects what happens if you call the `encode` or `decode` methods without a parameter. Thus question seems to be about not calling those methods *at all*, so the default encoding doesn't make much difference. – Arthur Tacca Feb 11 '20 at 20:06
  • By the way, the utf8 and ASCII encodings ate equivalent for any valid ASCII character (utf8 was designed with that in mind) so it wouldn't make any difference anyway. – Arthur Tacca Feb 11 '20 at 20:07
  • I'm not shure why that library would need an ascii string as well but the meaning of `str` changed with the python versions. In Python2 it meant bytes(ascii) in Python3 it's Unicode Points(utf-8). – Jakob F Feb 11 '20 at 20:09
  • In python2 if you needed unicode strings you used `unicode`. In python3 if you need byte(ascii) strings you can use `bytes`. – Jakob F Feb 11 '20 at 20:10
  • I think you you have the right idea but you're confusing terminology. "utf8" is a way of encoding Unicode strings as bytes. In Python 3, `str` is Unicode but does *not* use UTF8 internally, and even if it did you couldn't tell because there's no way to access the bytes inside it directly – instead you have to call `encode()` which encodes it using the encoding you specify. utf8 is the default there but that's just to save you some typing. In other words, it's not the type (`str` or `bytes`) that has the encoding, it's the `str` to `bytes` conversion that has the encoding. – Arthur Tacca Feb 11 '20 at 20:45
  • It's also not true to say that `bytes` in python 3 is ASCII, or any other particular encoding for that matter. For example, the result of `"foo".encode()` is a `bytes` that contains the bytes of a utf8 encoded string while the result of `"foo".encode("utf16")` contains the bytes of a utf16 encoded string. It's especially misleading to say that `bytes` is ASCII because bytes contains numbers up to 255 but all ASCII code points are below 128. – Arthur Tacca Feb 11 '20 at 20:48
  • 1
    The reason this library needs bytes is that it is a networking library, and all networking protocols are in terms of bytes. This is not at all changed from Python 2. Add you said, it is just the name of the bytes type and the notation for it that changed in Python 3. – Arthur Tacca Feb 11 '20 at 20:49