Reputation: 1
Miniedit GUI is showing error (as given below) when trying to export l2 script. I am running the Miniedit python file as python 3.6 as it was showing errors when opening with default python installed 2.7.
Error message:
File "/usr/lib/python3.6/tkinter/__init__.py"
TypeError: a byte -like object is required, not 'str'
Upvotes: 0
Views: 2265
Reputation: 147
Refer this comment on github. It solved for me.
line 2019 needs to be changed in
miniedit.py
for widget, item in self.widgetToItem:
it should be for widget, item in self.widgetToItem.items():
because items()
must be called on dict and it is correct everwhere else other than this line..mn
fileremove
self.convertJsonUnicode
call in line 1444 ofmininet.py
loadedTopology = self.convertJsonUnicode(json.load(f))
just use loadedTopology = json.load(f)
. The loadedTopology
dict keys are loaded as bytes when using convertJsonUnicode
which should actually be strings.Upvotes: -1
Reputation: 1
I am using python3 version 3.10.12. Ubuntu 22.04
This is the error i was getting in terminal
Exception in Tkinter callback
Traceback (most recent call last):
File "/usr/lib/python3.10/tkinter/__init__.py", line 1921, in __call__
return self.func(*args)
File "/home/muhammad/mininet/examples/miniedit.py", line 1508, in loadTopology
hosts = loadedTopology['hosts']
KeyError: 'hosts'
I think the problem lies in the way miniedit saves and load the topology information. The topology information is loaded in dictionary whose key values are in byte-string. Notice b' prepended with every key-value. Also take note of b'hosts' key.
loadedTopology = {
b'application': {
b'dpctl': b'',
b'ipBase': b'10.0.0.0/8',
b'netflow': {
b'nflowAddId': b'0',
b'nflowTarget': b'',
b'nflowTimeout': b'600'
},
b'openFlowVersions': {
b'ovsOf10': b'1',
b'ovsOf11': b'0',
b'ovsOf12': b'0',
b'ovsOf13': b'0'
},
b'sflow': {
b'sflowHeader': b'128',
b'sflowPolling': b'30',
b'sflowSampling': b'400',
b'sflowTarget': b''
},
b'startCLI': b'0',
b'switchType': b'ovs',
b'terminalType': b'xterm'
},
b'controllers': [],
b'hosts': [
{
b'number': b'1',
b'opts': {
b'hostname': b'h1',
b'nodeNum': 1,
b'sched': b'host'
},
b'x': b'130.0',
b'y': b'147.0'
},
{
b'number': b'2',
b'opts': {
b'hostname': b'h2',
b'nodeNum': 2,
b'sched': b'host'
},
b'x': b'150.0',
b'y': b'280.0'
}
],
b'links': [],
b'switches': [],
b'version': b'3'
}
Now open miniedit.py file in vs code the file is located in mininet/examples folder. Go to line something 1507. The starting code would look like this
hosts = loadedTopology['hosts']
# print(hosts)
for host in hosts:
nodeNum = host['number']
# more code ....
You can see the line
hosts = loadedTopology['hosts']
It expects key ['hosts'] but since loaded topology dictionary is in byte strings it we are giving it b'hosts' as key which it does not wants.
To change this we need to decode each byte-string in loadedTopology dictionary to regular strings recursively.
Go to line something 1447. Where the loadTopology function is defined like
def loadTopology( self ):
"Load command."
c = self.canvas
# more code ...
above loadTopology definition add another function which we would use for decoding
def decode_byte_strings(self,data):
if isinstance(data, dict):
decoded_dict = {}
for key, value in data.items():
if isinstance(key, bytes):
key = key.decode()
if isinstance(value, bytes):
value = value.decode()
decoded_dict[key] = self.decode_byte_strings(value)
return decoded_dict
elif isinstance(data, list):
return [self.decode_byte_strings(item) for item in data]
else:
return data
Now we just need to use it in loadTopology decode_byte_strings function. See the last line in code below
def decode_byte_strings(self,data):
if isinstance(data, dict):
decoded_dict = {}
for key, value in data.items():
if isinstance(key, bytes):
key = key.decode()
if isinstance(value, bytes):
value = value.decode()
decoded_dict[key] = self.decode_byte_strings(value)
return decoded_dict
elif isinstance(data, list):
return [self.decode_byte_strings(item) for item in data]
else:
return data
def loadTopology( self ):
"Load command."
c = self.canvas
myFormats = [
('Mininet Topology','*.mn'),
('All Files','*'),
]
f = tkFileDialog.askopenfile(filetypes=myFormats, mode='rb')
if f is None:
return
self.newTopology()
loadedTopology = self.convertJsonUnicode(json.load(f))
# Here we have used decoding function
loadedTopology = self.decode_byte_strings(loadedTopology)
See the last line in code. We have used the functions. Now the loadedTopology dictionary will contain regular strings
Now save the file and run miniedit.py.
That's how i solved my problem, by the way this is my second answer on stackoverflow. so i am currently not that great at providing concise answers. I hope i explained in as much relevant and concise way as i could
Thanks for reading. Have a nice Day.
Upvotes: 0
Reputation: 1
I used Python 2 to run Mininedit on Mininet 2.3.0, and it is working properly.
Command below:
$ sudo -E python2 ~/mininet/examples/miniedit.py
Upvotes: 0
Reputation: 31
I had the same problem, all I did was change the default file path to desktop /usr/lib/python2.7/dist-packages/mininet/examples
path to Desktop
and it works,
so all you have to do is change the file path
Upvotes: 0
Reputation: 11
Change the line 1452 to:
self.appPrefs.update(loadedTopology['application'])
And the lines 1686 and 1705 to:
f = open(fileName, 'w')
for more information Fix python3 compatibility issues in miniedit
Upvotes: 1
Reputation: 1
Go to where miniedit.py locate then open it with text editor.
Go to line 1702 and change to:
f = open(fileName, 'w')
Upvotes: 0