একটি অভিধানের একটি স্ট্রিং উপস্থাপনা একটি অভিধানে রূপান্তর করবেন?


767

আমি নীচের স্ট্রিংয়ের মতো strএকটি এর উপস্থাপনাটিকে কীভাবে রূপান্তর করতে পারি ?dictdict

s = "{'muffin' : 'lolz', 'foo' : 'kitty'}"

আমি ব্যবহার না করা পছন্দ করি eval। আমি আর কি ব্যবহার করতে পারি?

এর মূল কারণ হ'ল তিনি লিখেছেন আমার সহকর্মী শ্রেণীর একটি, সমস্ত ইনপুটকে স্ট্রিতে রূপান্তরিত করে। এই সমস্যাটি মোকাবেলা করার জন্য আমি তার ক্লাসগুলি পরিবর্তন এবং সংশোধন করার মুডে নেই।


1
আপনি পাইথন 2.6 ব্যবহার করতে পারবেন না, তাহলে আপনি মত সরল safeeval implmenentation ব্যবহার করতে পারেন code.activestate.com/recipes/364469 যাতে আপনি সব স্থূল কাজ নিজেকে করতে হবে না এটা পাইথন কম্পাইলার উপর piggybacks।
নেড ব্যাচেল্ডার

11
দ্রষ্টব্য : যারা এখানে প্রতারণামূলকভাবে অনুরূপ JSON ডেটা নিয়ে আসে, আপনি তার পরিবর্তে পাইথনে পার্সে JSON পড়তে চান । জেএসওএন পাইথনের মতো জিনিস নয় । আপনি যদি "আপনার স্ট্রিং প্রায় ডবল কোট আপনি সম্ভবত JSON তথ্য আছে। এছাড়াও আপনি খুঁজতে পারেন null, trueঅথবা false, পাইথন সিনট্যাক্স ব্যবহার None, Trueএবং False
মার্টিজন পিটারস

উত্তর:


1167

পাইথন ২.6 থেকে শুরু করে আপনি বিল্ট-ইন ব্যবহার করতে পারেন ast.literal_eval:

>>> import ast
>>> ast.literal_eval("{'muffin' : 'lolz', 'foo' : 'kitty'}")
{'muffin': 'lolz', 'foo': 'kitty'}

এটি ব্যবহারের চেয়ে নিরাপদ eval। যেমন এর নিজস্ব ডক্স বলে:

>>> সহায়তা (ast.literal_eval)
মডিউল এস্টে আক্ষরিক_বেলা ফাংশনে সহায়তা করুন:

literal_eval (node_or_string)
    এক্সপ্রেশন নোড বা পাইথনযুক্ত স্ট্রিং নিরাপদে মূল্যায়ন করুন
    অভিব্যক্তি। সরবরাহ করা স্ট্রিং বা নোডে কেবলমাত্র নিম্নলিখিতটি থাকতে পারে
    পাইথন আক্ষরিক কাঠামো: স্ট্রিং, সংখ্যা, টিপলস, তালিকা, ডিক্টস, বুলিয়ানস,
    এবং কিছুই না।

উদাহরণ স্বরূপ:

>>> eval("shutil.rmtree('mongo')")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1, in <module>
  File "/opt/Python-2.6.1/lib/python2.6/shutil.py", line 208, in rmtree
    onerror(os.listdir, path, sys.exc_info())
  File "/opt/Python-2.6.1/lib/python2.6/shutil.py", line 206, in rmtree
    names = os.listdir(path)
OSError: [Errno 2] No such file or directory: 'mongo'
>>> ast.literal_eval("shutil.rmtree('mongo')")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/opt/Python-2.6.1/lib/python2.6/ast.py", line 68, in literal_eval
    return _convert(node_or_string)
  File "/opt/Python-2.6.1/lib/python2.6/ast.py", line 67, in _convert
    raise ValueError('malformed string')
ValueError: malformed string

আমার যুক্ত করা উচিত যে আপনাকে ast.literal_eval দিয়ে স্ট্রিংটি স্যানিটাইজ করতে হবে। (স্ট্রিংয়ে কোট / ডাবল কোটগুলি রক্ষা পেয়েছে তা নিশ্চিত করুন)
পাওলো মাতোস

আমি এই ত্রুটিটি পেয়েছি আমি উইন্ডোজ 7 x64 ফাইল "ডি: \ পাইথন 26 \ lib \ ast.py", লাইন 48 এ লাইটন ২.6 (x86) এ আছি, আক্ষরিক_ভিত্তিক নোড_অর_স্ট্রিং = পার্সে (নোড_অর_স্ট্রিং, মোড = 'ইভাল') ফাইল "ডি : \ পাইথন 26 \ lib \ ast.py ", লাইন 36, পার্স রিটার্ন সংকলনে (এক্সপ্রেস, ফাইলের নাম, মোড, পাইসিএফিউটিএলওয়াইএসটি) ফাইল" <অজ্ঞাত> ", লাইন 1

"dict(a=1)"স্টাইল স্ট্রিং সম্পর্কে কি ?
n611x007

এটি কোনও অভিধানের মধ্যে এনাম মানটির জন্য কাজ করে বলে মনে হচ্ছে না। উদাহরণস্বরূপ: d = "col 'কল': <Colors.RED: 2>, 'ভাল': 2}"
shivshnkr

3
জসন.ডাম্পস এবং জসন.লোডগুলি ইনসাইড কেন ব্যবহার করবেন না, আমি এই সমাধানটি আরও বেশি উন্নত না করে ইভাল ব্যবহার করে দেখতে পেলাম
অরোস 132

232

https://docs.python.org/3.8/library/json.html

JSON এই সমস্যাটি সমাধান করতে পারে যদিও এর ডিকোডারটি কী এবং মানগুলির চারপাশে ডাবল উদ্ধৃতি চায়। আপনি যদি একটি প্রতিস্থাপন হ্যাক আপত্তি না ...

import json
s = "{'muffin' : 'lolz', 'foo' : 'kitty'}"
json_acceptable_string = s.replace("'", "\"")
d = json.loads(json_acceptable_string)
# d = {u'muffin': u'lolz', u'foo': u'kitty'}

নোট করুন যে আপনার কী বা মানগুলির অংশ হিসাবে যদি আপনার একক উদ্ধৃতি থাকে তবে এটি অক্ষত অক্ষর প্রতিস্থাপনের কারণে ব্যর্থ হবে। এই সমাধানটি কেবলমাত্র তখনই প্রস্তাবিত হয় যদি আপনার কাছে বিভাজন সমাধানের একটি দৃ strong় বিদ্বেষ থাকে।

জেসন একক উক্তি সম্পর্কে আরও: জেএসএন-তে একক উদ্ধৃতি থেকে রক্ষা পাওয়ার কারণে জ্যাকউন. পার্সজেএসএন "অবৈধ জেএসএন" ত্রুটি ফেলেছে




1
আমি এই সমাধান খুঁজছিলাম। +1ডিকোডারটি কী এবং মানগুলির চারপাশে ডাবল উদ্ধৃতি চায় তা অবগত করার জন্য।
এইচ 8 পাঠক

আর একটি সমস্যা হচ্ছে "{0: 'Hello'}"
ফিন

3
যদি আপনার পিছনে কমা রয়েছে (JSON অনুগত নয়) এটিও ব্যর্থ হয়, উদাহরণস্বরূপ: "uff 'মাফিন': 'ললজ', '
ফু

159

ব্যবহার json.loads:

>>> import json
>>> h = '{"foo":"bar", "foo2":"bar2"}'
>>> d = json.loads(h)
>>> d
{u'foo': u'bar', u'foo2': u'bar2'}
>>> type(d)
<type 'dict'>

13
আমি মনে করি না যে এটি অপের উত্তরটির জবাব দেয়। আমরা স্ট্রিংকে s = "{'মাফিন":' লোলজ ',' ফু ':' কিটি '} "ডিক্টারে রূপান্তর করতে json.laads কীভাবে ব্যবহার করব?
টেকনাজি

এই মুদ্রণটি আউটপুটে কেন 'ইউ' ?? উদাহরণস্বরূপ - str = '{"1": "পি", "2": "এন", "3": "এম"}' d = জসন.লোডস (স্ট্র) প্রিন্ট ডি আউটপুটটি: {u'1 ': u'P ', u'3': u'M ', u'2': u'N '}
ব্যবহারকারী 905

2
@ টেকনাজী: জসন.লোডস (এইচ.প্লেস ("" "," ""))
এনটিজি

তবে সীমাবদ্ধতা রয়েছে, যেমন: h = 'm "muffin": "lolz", "foo": "Kitty",}', h h '' m "muffin's": "lolz", "foo": "কিটি "} ', (একই মন্তব্যে ঠিক একই মন্তব্যের অংশটি লক্ষ্য করা গেছে ... এখনও সম্পূর্ণতার জন্য এখানে
রইল

4
আমার মতে, এটি সবচেয়ে সংক্ষিপ্ত এবং সহজতম উপায় ... অবশ্যই আমি ব্যক্তিগতভাবে পছন্দ করি।
নস্টরডামাস

35

ওপির উদাহরণ হিসাবে:

s = "{'muffin' : 'lolz', 'foo' : 'kitty'}"

আমরা স্ট্রমে এই জাতীয় অ-মানক জসন মোকাবেলা করতে ইয়ামল ব্যবহার করতে পারি :

>>> import yaml
>>> s = "{'muffin' : 'lolz', 'foo' : 'kitty'}"
>>> s
"{'muffin' : 'lolz', 'foo' : 'kitty'}"
>>> yaml.load(s)
{'muffin': 'lolz', 'foo': 'kitty'}

1
এটি 'হ্যাঁ' এবং 'না' স্ট্রিংগুলিকে সত্য / মিথ্যাতে রূপান্তরিত করবে
এরিক মার্কোস

23

যদি স্ট্রিংটি সর্বদা বিশ্বাসযোগ্য হতে পারে তবে আপনি ব্যবহার করতে পারেন eval(বা literal_evalপ্রস্তাবিত হিসাবে ব্যবহার করুন ; স্ট্রিংটি যাই হোক না কেন এটি নিরাপদ)) অন্যথায় আপনার পার্সার প্রয়োজন। কোনও জেএসএন পার্সার (যেমন সিম্পজসন) কাজ করবে যদি তিনি কেবল এমন কোনও সামগ্রী জেএসওএন স্কিমের সাথে মানানসই সঞ্চয় করেন।


8
২.6 থেকে শুরু করে সিম্পজসনকে পাইথন স্ট্যান্ডার্ড লাইব্রেরিতে জসন মডিউল হিসাবে অন্তর্ভুক্ত করা হয়েছে।
এলি কোর্টরাইট

11
হ্যাঁ, এটি একটি ভাল উত্তর, তবে নোট করুন যে আনুষ্ঠানিকভাবে জেএসওএন একক-উদ্ধৃত স্ট্রিংগুলিকে সমর্থন করে না, যেমন পোস্টারটির উদাহরণে দেওয়া আছে।
বেন হোয়েট

19

ব্যবহার jsonastগ্রন্থাগার মেমরি অনেক এবং এবং ধীর হ্রাস। আমার একটি প্রক্রিয়া রয়েছে যার 156Mb টেক্সট ফাইলটি পড়া দরকার। Astরূপান্তর অভিধানের জন্য 5 মিনিট বিলম্ব jsonএবং 60% কম মেমরি ব্যবহার করে 1 মিনিট!


13
তবে এর সীমাবদ্ধতা রয়েছে: "
f

12

সংক্ষেপ:

import ast, yaml, json, timeit

descs=['short string','long string']
strings=['{"809001":2,"848545":2,"565828":1}','{"2979":1,"30581":1,"7296":1,"127256":1,"18803":2,"41619":1,"41312":1,"16837":1,"7253":1,"70075":1,"3453":1,"4126":1,"23599":1,"11465":3,"19172":1,"4019":1,"4775":1,"64225":1,"3235":2,"15593":1,"7528":1,"176840":1,"40022":1,"152854":1,"9878":1,"16156":1,"6512":1,"4138":1,"11090":1,"12259":1,"4934":1,"65581":1,"9747":2,"18290":1,"107981":1,"459762":1,"23177":1,"23246":1,"3591":1,"3671":1,"5767":1,"3930":1,"89507":2,"19293":1,"92797":1,"32444":2,"70089":1,"46549":1,"30988":1,"4613":1,"14042":1,"26298":1,"222972":1,"2982":1,"3932":1,"11134":1,"3084":1,"6516":1,"486617":1,"14475":2,"2127":1,"51359":1,"2662":1,"4121":1,"53848":2,"552967":1,"204081":1,"5675":2,"32433":1,"92448":1}']
funcs=[json.loads,eval,ast.literal_eval,yaml.load]

for  desc,string in zip(descs,strings):
    print('***',desc,'***')
    print('')
    for  func in funcs:
        print(func.__module__+' '+func.__name__+':')
        %timeit func(string)        
    print('')

ফলাফল:

*** short string ***

json loads:
4.47 µs ± 33.4 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
builtins eval:
24.1 µs ± 163 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
ast literal_eval:
30.4 µs ± 299 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
yaml load:
504 µs ± 1.29 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

*** long string ***

json loads:
29.6 µs ± 230 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
builtins eval:
219 µs ± 3.92 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
ast literal_eval:
331 µs ± 1.89 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
yaml load:
9.02 ms ± 92.2 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

উপসংহার: json.loads পছন্দ করুন


5
বাদে এটি তার একক-উদ্ধৃত স্ট্রিংয়ের সাথে কাজ করবে না, যা তার প্রাথমিক সমস্যার অংশ ছিল। পারফরম্যান্স উল্লেখ করা হয়নি।
মাইকেল ক্যাম্পবেল

1
বাহ .... সুপার ব্যাখ্যার ....
চ্যারি

5
string = "{'server1':'value','server2':'value'}"

#Now removing { and }
s = string.replace("{" ,"")
finalstring = s.replace("}" , "")

#Splitting the string based on , we get key value pairs
list = finalstring.split(",")

dictionary ={}
for i in list:
    #Get Key Value pairs separately to store in dictionary
    keyvalue = i.split(":")

    #Replacing the single quotes in the leading.
    m= keyvalue[0].strip('\'')
    m = m.replace("\"", "")
    dictionary[m] = keyvalue[1].strip('"\'')

print dictionary

3
এই পদ্ধতির অনেক ভুল। একটি কী এর মান থাকে {বা }। বাসা বাঁধলে কী হয় dict। মান থাকলে কি হবে ,??
ওম সাও

4

কোনও লিব ব্যবহার করা হয় না:

dict_format_string = "{'1':'one', '2' : 'two'}"
d = {}
elems  = filter(str.isalnum,dict_format_string.split("'"))
values = elems[1::2]
keys   = elems[0::2]
d.update(zip(keys,values))

দ্রষ্টব্য: এটি হার্ডকোডযুক্ত যেমন split("'")কেবল স্ট্রিংয়ের জন্য কাজ করবে যেখানে ডেটা "একক উদ্ধৃত" রয়েছে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.