2

I have a need for a tool to spit out commands to a telnet device that requires none printable chars, such as carriage-returns and line-feeds. In python itself this is achieved with something like the following....

myDevice.send(b'command\n\r')

This would result in 9 bytes being sent to the device.

I would like to enter such a string into a Tkinter entry box. However it seems the Tk entry box is too clever for its own good and escapes the \ so I always get \\ whenever I introduce \r\n or \x0a etc. In other words it is always printable.

I have tried endlessly to render the resultant string into what I need but without joy. I have included a small example below that should illustrate the problem.

from tkinter import *

def show_entry_fields():
   print(e1.get().encode())

def show_string():
    myString = b'hello\n'
    print(myString)

master = Tk()
Label(master, text="Enter string with \\n").grid(row=0)

e1 = Entry(master)
e1.insert(10,"enter with escape char")

e1.grid(row=0, column=2)

Button(master, text='Quit', command=master.quit).grid(row=3, column=0, sticky=W, pady=4)
Button(master, text='Show Entry', command=show_entry_fields).grid(row=3, column=1, sticky=W, pady=4)
Button(master, text='Show myString', command=show_string).grid(row=3, column=2, sticky=W, pady=4)

mainloop( )

The following was entered into the tk entry box: 'hello\n'

This is what comes out from a print: b'hello\\n'

What I actually want to see is this: b'hello\n'

And once sent to the device becomes just 6 bytes.

sanyassh
  • 8,100
  • 13
  • 36
  • 70
  • 1
    I'm not really an expert on encoding so I'll post this as a comment instead of an answer sice this may not be the best way, but `e1.get().encode().decode('unicode_escape').encode()` seems to give you what you want. – fhdrsdg May 09 '19 at 09:24
  • 1
    when you put `"\n"` in Entry then it is treaded as normal string with two chars `"\"` and `"n"`, not as new line. You can replace it with `b'hello\\n'.replace(b'\\n', b'\n')`. But you can also always get text without `'\n'` and always append `b'\n'` – furas May 09 '19 at 09:31
  • Many thanks 'fhdrsdg' I tried this ```e1.get().encode().decode('unicode_escape').encode()``` and it works, however it only works for ```\x00``` to ```\x0f```. Anything higher than ```\xa0``` generates two bytes. - almost there..... – Rupert Powell May 09 '19 at 09:54

2 Answers2

2

The following works for ALL chars, including \n, \r, \t and \x00 - \xff

print(e1.get().encode('latin-1').decode('unicode_escape').encode('latin-1'))

  • 1
    `latin1`? I can't speak for every operating system, but at least on most UNIX-y systems I've seen, it's conventional to use UTF-8 unless there's a compelling reason to do otherwise. And `e1.get().encode('utf-8')` is a lot shorter than the mouthful given here. :) – Charles Duffy Dec 01 '19 at 20:53
0

Try this code:

import ast
def show_entry_fields():
    print(ast.literal_eval(f'b"{e1.get()}"'))

This evaluates the content of the Entry as a bytes literal. Note that it requres " to be escaped as \".

Maximouse
  • 4,170
  • 1
  • 14
  • 28