2012-02-16 16 views
17

Chciałbym utworzyć słownik z pliku tekstowego, który mam, którego zawartość jest w formacie "słownika". Oto przykład co plik zawiera:Python: Utwórz słownik z tekstu/pliku w formacie słownika

{ 'płowa': [1] 'Sermersheim' [3] 'sonji' [2] 'Scheuring' [2]}

To jest dokładnie to, że zawiera 125 000 wpisów. Jestem w stanie czytać w pliku tekstowym za pomocą read(), ale tworzy zmienną dosłownym tekście pliku nawet kiedy zainicjować zmienną

dict = {}

+8

'ast.literal_eval' – JBernardo

+1

@JBernardo +1 jako tak długo, jak masz Python 2.6 lub nowszy, w ten sposób możesz iść. Moduł 'ast' został wprowadzony w wersji 2.5, ale nie miał funkcji pomocniczych (takich jak' literal_eval'). Te pojawiły się w wersji 2.6. –

+0

@JBernardo, najlepsza odpowiedź – dzhioev

Odpowiedz

23

Można użyć eval wbudowane. Na przykład, będzie to działać, jeśli każdy wpis słownik jest na innej linii:

with open('myfile.txt','r') as inf: 
    dict_from_file = eval(inf.read()) 
:

dicts_from_file = [] 
with open('myfile.txt','r') as inf: 
    for line in inf: 
     dicts_from_file.append(eval(line))  
# dicts_from_file now contains the dictionaries created from the text file 

Alternatywnie, jeśli plik jest po prostu jednym wielkim słowniku (nawet na wielu liniach), można to zrobić

Jest to prawdopodobnie najprostszy sposób na zrobienie tego, ale nie jest najbezpieczniejszy. Jak wspomnieli inni w swoich odpowiedziach, eval ma pewne nieodłączne ryzyko bezpieczeństwa. Alternatywą, jak wspomniał JBernardo, jest użycie ast.literal_eval, która jest o wiele bezpieczniejsza niż eval, ponieważ będzie tylko oceniać ciągi zawierające literały. Możesz po prostu wymienić wszystkie połączenia na eval w powyższych przykładach za pomocą ast.literal_eval po zaimportowaniu modułu ast.

Jeśli używasz Pythona 2.4, nie będziesz mieć modułu ast i nie będziesz mieć instrukcji with. Kod będzie wyglądać mniej więcej tak:

inf = open('myfile.txt','r') 
dict_from_file = eval(inf.read()) 
inf.close() 

Nie zapomnij zadzwonić pod numer inf.close(). Piękno instrukcji with jest to, że robią to za Ciebie, nawet jeśli blok kodu w instrukcji with podnosi wyjątek.

+0

Co, jeśli to tylko ściana z tekstem? To dosłownie ciągły ciąg rozpoczynający się od {i kończący się na}. – Jared

+0

Powinno nadal działać, jeśli istnieje tylko jedna linia. – DynamiteReed

+0

Będzie działać, jeśli jest tylko jedna linia, ale nie będzie działać, jeśli słownik zostanie rozłożony na więcej niż jedną linię. Dodałem dodatkowy kod dla tej sprawy. –

0

To dla mnie wygląda jak json. Użyj modułu json, jeśli tak.

To dla mnie wygląda jak yaml. Użyj opcji pyyaml module, jeśli tak. (Zgodnie z sugestią @jcollado).

Nie można użyć modułu json, ponieważ jest to ścisłe, jeśli chodzi o jego dane wejściowe.

+3

To nie jest JSON: używa cudzysłowów zamiast podwójnych cudzysłowów. –

+0

@NedBatchelder: Tak. Nie zdawałem sobie sprawy, że moduł 'json' ma ścisłe znaczenie. – Marcin

1

Użyj funkcji eval.

Na przykład

dict = eval(open("yourfile.txt").read()) 
+0

+1 'eval' jest zdecydowanie najprostszą rzeczą do zrobienia. Komentarz napisany przez @JBernardo na temat 'ast.literal_eval' jest bezpieczniejszy, ponieważ zezwala tylko na ciągi, liczby, krotki, listy, dykty, wartości logiczne i Brak. Po prostu coś do rozważenia. – istruble

1

Mimo to bardzo zniechęcam do korzystania z eval. Może to skutkować problemami bezpieczeństwa, jeśli nie masz pełnej kontroli nad plikiem wejściowym. Wystarczy zaimportować słownik i zapisać go za pomocą modułu json lub.

+0

Zgadzam się, że eval jest gigantycznym zagrożeniem bezpieczeństwa, jeśli jest używane regularnie lub w kodzie produkcyjnym, I zinterpretował pierwotne pytanie do rozdania z izolowanym fragmentem kodu, który pochodzi z zaufanego źródła i znajduje się już w pliku tekstowym. Biorąc pod uwagę taką sytuację, niewiele więcej możesz zrobić. – DynamiteReed

+0

Jest w pliku statycznym z zaufanego źródła, tak! – Jared

+0

I nie miałem szczęścia z plikami pikle. Mam te same informacje w pliku .pickle, ale nie mogę go ponownie załadować. Ten kod jest uruchamiany w zastrzeżonym systemie bez dostępu do Internetu. – Jared

3

Używanie eval może być niebezpieczne.Jeśli json nie działa, następnie polecam korzystania yaml który wydaje się działać dobrze ze swoim przykładzie wejścia:

>>> import yaml 
>>> yaml.load("{'fawn': [1], 'sermersheim': [3], 'sonji': [2], 'scheuring': [2]}") 
{'fawn': [1], 'scheuring': [2], 'sermersheim': [3], 'sonji': [2]} 
+0

Ah, chciałbym użyć tego, ale nie mam modułu i system, na którym uruchamiany jest kod, nie ma dostępu do Internetu. Dzięki i tak! – Jared

+0

Mimo to warto rozważyć instalację ze źródła. Zgodnie z dokumentacją powinno to być tak proste, jak: 'python setup.py install'. – jcollado

1

nie jest to produkcja rozwiązanie gotowe i może nie pracować z plikiem swojej wielkości, ale jeśli trzeba w prosty sposób i może poprzedzić złożyć do

my_dict = {'fawn': [1], 'sermersheim': [3], 'sonji': [2], 'scheuring': [2]} 

następnie można zmienić jego nazwę do pliku python i po prostu importować

from my_file import my_dict