0

I have a string:

s = "['9780310714675', '9780763630614', '9781416925330', '9780310714569']"

when loaded into memory, this becomes:

'[\'9780310714675\', \'9780763630614\', \'9781416925330\', \'9780310714569\']'

I wonder how to convert it to a list of strings:

strList = ['9780310714675', '9780763630614', '9781416925330', '9780310714569']

I have tried to do this using:

strList = json.loads(s)

but then I got the following error:

Traceback (most recent call last):
  File "/home/xxx/dev/python/data-processing/MongoDB/query.py", line 101, in <module>
    isbnList = marcQuery.stringToStringList(isbnString)
  File "/home/xxx/dev/python/data-processing/MongoDB/query.py", line 74, in stringToStringList
    strList = json.loads(s)
  File "/home/xxx/anaconda3/lib/python3.7/json/__init__.py", line 348, in loads
    return _default_decoder.decode(s)
  File "/home/xxx/anaconda3/lib/python3.7/json/decoder.py", line 337, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/home/xxx/anaconda3/lib/python3.7/json/decoder.py", line 355, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 2 (char 1)

Can anyone give me some hints on how to do this?

mkrieger1
  • 19,194
  • 5
  • 54
  • 65
Ken Tsoi
  • 1,195
  • 1
  • 17
  • 37
  • 2
    You can `eval` it. Clearly, this is the `__str__` representation of some list. Don't do that, you should use an actual serialization format. – juanpa.arrivillaga Oct 04 '20 at 00:07
  • 1
    The string is not in the JSON format. – DYZ Oct 04 '20 at 00:09
  • 1
    @juanpa.arrivillaga: This one can be handled with `ast.literal_eval` safely. It's not legal JSON because JSON uses double-quotes for strings, never single-quotes. – ShadowRanger Oct 04 '20 at 00:10

1 Answers1

1

Just use the eval() function. It will evaluate a string as if it was python expression.

strList = eval(s)

Edit: Some people argue ast.literal_eval is better. And this is 100% true for production code and any case where you can't trust the source of the input. However when learning python and writing hobby projects, you know you can trust the input because you wrote it.

import ast

def read_value(string):
   try:
        return ast.literal_eval(string)
   except:
        print("Unsafe to eval: \"" + string "\"")

I don't believe telling new programmers to always follow proper data safety is helpful while learning. In fact, I would rather they experiment and learn from mistakes on their own.

"I know you don't understand how this works yet, but just copy this magic code block instead because it is safer"

Reference on why they are different: https://stackoverflow.com/a/15197698/5987669

Locke
  • 7,626
  • 2
  • 21
  • 41
  • 2
    [Eval really is dangerous](https://nedbatchelder.com/blog/201206/eval_really_is_dangerous.hml). – DYZ Oct 04 '20 at 00:10
  • Why is eval() dangerous? – Ken Tsoi Oct 04 '20 at 00:12
  • 2
    For hobby projects and learning to code it is easier to use. That being said, it never use it in production code. Enforcing truly safe code is good, but I don't think it is worth the extra work in this case. @KenTsoi https://stackoverflow.com/a/15197698/5987669 – Locke Oct 04 '20 at 00:12
  • ic thanks! for my usecase it should be OK though. – Ken Tsoi Oct 04 '20 at 00:16
  • 4
    @KenTsoi it's dangerous with untrusted inputs because it can evaluate arbitrary code. Probably it's not a big deal for the OP, but the fundamental problem is the OP is using the string representation of a list as a serialization format when they should be using an actual serialization format. – juanpa.arrivillaga Oct 04 '20 at 00:25
  • ic thanks, I will use ast.literal_eval() then – Ken Tsoi Oct 04 '20 at 23:38