1

I am running a subprocess: packets = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) and collecting the output. It returns stdout = {'port2_tx': 1000L, 'port2_rx': 1000L, 'port1_rx': 1000L, 'port1_tx': 1000L}\n Edit: This subprocess is a python2 tool (not convertible to 3)

I want to convert this to a dictionary and getting:

Traceback (most recent call last):
  File "robot/lib/libraries/WarpTrafficLib.py", line 31, in <module>
    send_warp_traffic('172.18.0.48','***','***', _create_streams_arg(stream), 10)
  File "robot/lib/libraries/WarpTrafficLib.py", line 19, in send_warp_traffic
    return dict(out.strip())
TypeError: cannot convert dictionary update sequence element #0 to a sequence

>>> x
b"{'port2_tx': 1000L, 'port2_rx': 1000L, 'port1_rx': 1000L, 'port1_tx': 1000L}"
>>> ast.literal_eval(x)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/ast.py", line 85, in literal_eval
    return _convert(node_or_string)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/ast.py", line 84, in _convert
    raise ValueError('malformed node or string: ' + repr(node))
ValueError: malformed node or string: b"{'port2_tx': 1000L, 'port2_rx': 1000L, 'port1_rx': 1000L, 'port1_tx': 1000L}"
>>> import json
>>> d = json.loads(x)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/__init__.py", line 354, in loads
    return _default_decoder.decode(s)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/decoder.py", line 339, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/decoder.py", line 355, in raw_decode
    obj, end = self.scan_once(s, idx)
json.decoder.JSONDecodeError: Expecting property name enclosed in double quotes: line 1 column 2 (char 1)

Tried both json and ast.literal_eval

Do I need to strip the L from the string before I can load it as a dictionary or is there a better way?

bison
  • 739
  • 5
  • 21
  • 1
    Possible duplicate of [Convert a String representation of a Dictionary to a dictionary?](https://stackoverflow.com/questions/988228/convert-a-string-representation-of-a-dictionary-to-a-dictionary) – Aran-Fey Aug 22 '18 at 15:33
  • @Aran-Fey tried the options, nothing. Will update – bison Aug 22 '18 at 15:38
  • Ah, I forgot that the `L` syntax no longer exists in python 3. – Aran-Fey Aug 22 '18 at 15:40
  • That "number + L" syntax is for long ints in Python 2 (which are equivalent to just ints in Python 3). You won't be able to evaluate it directly. Maybe `2to3` or `six` has a tool you could use. Also you need to convert the bytes object to string before you can use it. – wjandrea Aug 22 '18 at 15:40
  • Thanks @wjandrea I will take a look – bison Aug 22 '18 at 15:42

1 Answers1

0

So turns out the following code fails in Python 3:

>>> 1L
1L
>>> long(1)
1L

If you do need it this works on both Python 2 and Python 3 without 2to3 conversion:

>>> import sys
>>> if sys.version_info > (3,):
...     long = int
>>> long(1)
1L

For my issues I just had to solve with:

x = b"{'port2_tx': 1000L, 'port2_rx': 1000L, 'port1_rx': 1000L, 'port1_tx': 1000L}"
x = x.replace(b'L',b'')
ast.literal_eval(x.decode('utf-8'))
{'port2_tx': 1000, 'port2_rx': 1000, 'port1_rx': 1000, 'port1_tx': 1000}
bison
  • 739
  • 5
  • 21