Лучший способ получить значения переменных из текстового файла - Python - Json - PullRequest
35 голосов
/ 29 мая 2009

Ссылаясь на этот вопрос , у меня есть похожая, но не та же проблема ..

По дороге у меня будет какой-нибудь текстовый файл, структурированный как:

var_a: 'home'
var_b: 'car'
var_c: 15.5

И мне нужно, чтобы python прочитал файл, а затем создал переменную с именем var_a со значением 'home' и т. Д.

Пример:

#python stuff over here
getVarFromFile(filename) #this is the function that im looking for
print var_b
#output: car, as string
print var_c
#output 15.5, as number.

Возможно ли, я имею в виду, даже сохранить тип var?

Обратите внимание, что у меня есть полная свобода в структуре текстового файла, я могу использовать формат, который мне нравится, если предложенный мною не самый лучший.

РЕДАКТИРОВАТЬ : ConfigParser может быть решением, но мне оно не очень нравится, потому что в моем сценарии я буду ссылаться на переменные в файле с помощью

config.get("set", "var_name")

Но я полюблю ссылку на переменную напрямую, как я ее объявил в скрипте python ...

Есть ли способ импортировать файл как словарь Python?

О, последнее, учтите, что я точно не знаю, сколько переменных у меня будет в текстовом файле.

Редактировать 2 : Я очень заинтересован в решении JSON Стефана, потому что таким образом текстовый файл может быть просто прочитан на других языках (PHP, затем через AJAX JavaScript, например), но я потерпеть неудачу в чем-то во время действия этого решения:

#for the example, i dont load the file but create a var with the supposed file content
file_content = "'var_a': 4, 'var_b': 'a string'"
mydict = dict(file_content)
#Error: ValueError: dictionary update sequence element #0 has length 1; 2 is required
file_content_2 = "{'var_a': 4, 'var_b': 'a string'}"
mydict_2 = dict(json.dump(file_content_2, True))
#Error:
#Traceback (most recent call last):
#File "<pyshell#5>", line 1, in <module>
#mydict_2 = dict(json.dump(file_content_2, True))
#File "C:\Python26\lib\json\__init__.py", line 181, in dump
#fp.write(chunk)
#AttributeError: 'bool' object has no attribute 'write'

В какие проблемы я могу попасть с форматом JSON? И как я могу прочитать массив JSON в текстовом файле и преобразовать его в текст Python?

P.S .: Мне не нравится решение с использованием файлов .py; Я предпочитаю .txt, .inc,. Что бы не ограничивало один язык.

Ответы [ 9 ]

60 голосов
/ 29 мая 2009

Но мне очень понравится ссылаться на переменную direclty, как я ее объявил в скрипте python.

Если вы рады, что немного изменили свой синтаксис, просто используйте python и импортируйте модуль "config".

# myconfig.py:

var_a = 'home'
var_b = 'car'
var_c = 15.5

Тогда сделай

from myconfig import *

И вы можете ссылаться на них по имени в вашем текущем контексте.

24 голосов
/ 29 мая 2009

Использовать ConfigParser.

Ваша конфигурация:

[myvars]
var_a: 'home'
var_b: 'car'
var_c: 15.5

Ваш код Python:

import ConfigParser

config = ConfigParser.ConfigParser()
config.read("config.ini")
var_a = config.get("myvars", "var_a")
var_b = config.get("myvars", "var_b")
var_c = config.get("myvars", "var_c")
20 голосов
/ 29 мая 2009

Вы можете рассматривать ваш текстовый файл как модуль Python и загружать его динамически, используя imp.load_source:

import imp
imp.load_source( name, pathname[, file]) 

Пример:

// mydata.txt
var1 = 'hi'
var2 = 'how are you?'
var3 = { 1:'elem1', 2:'elem2' }
//...

// In your script file
def getVarFromFile(filename):
    import imp
    f = open(filename)
    global data
    data = imp.load_source('data', '', f)
    f.close()

# path to "config" file
getVarFromFile('c:/mydata.txt')
print data.var1
print data.var2
print data.var3
...
14 голосов
/ 29 мая 2009

Загрузите файл с JSON или PyYAML в словарь the_dict (см. Документ по JSON или PyYAML для этого шага, оба могут хранить тип данных) и добавьте словарь ваш глобальный словарь, например используя globals().update(the_dict).

Если вы хотите вместо этого в локальном словаре (например, внутри функции), вы можете сделать это следующим образом:

for (n, v) in the_dict.items():
    exec('%s=%s' % (n, repr(v)))

, пока это безопасно для использования exec. Если нет, вы можете использовать словарь напрямую.

5 голосов
/ 03 августа 2012

Другие решения, опубликованные здесь, не сработали для меня, потому что:

  • Мне просто нужны параметры из файла для обычного скрипта
  • import * не работает для меня, так как мне нужен способ переопределить их, выбрав другой файл
  • Просто файл с надписью был не в порядке, так как мне нужны были комментарии.

Итак, я использовал Configparser и globals().update()

Тестовый файл:

#File parametertest.cfg:
[Settings]
#Comments are no Problem
test= True
bla= False    #Here neither

#that neither

И это мой демонстрационный скрипт:

import ConfigParser

cfg = ConfigParser.RawConfigParser()
cfg.read('parametertest.cfg')       # Read file

#print cfg.getboolean('Settings','bla') # Manual Way to acess them

par=dict(cfg.items("Settings"))
for p in par:
    par[p]=par[p].split("#",1)[0].strip() # To get rid of inline comments

globals().update(par)  #Make them availible globally

print bla

Теперь это просто для файла с одним разделом, но его будет легко принять.

Надеюсь, это будет кому-то полезно:)

4 голосов
/ 22 марта 2012

Предположим, у вас есть файл с именем "test.txt" с:

a=1.251
b=2.65415
c=3.54
d=549.5645
e=4684.65489

И вы хотите найти переменную (a, b, c, d или e):

ffile=open('test.txt','r').read()

variable=raw_input('Wich is the variable you are looking for?\n')

ini=ffile.find(variable)+(len(variable)+1)
rest=ffile[ini:]
search_enter=rest.find('\n')
number=float(rest[:search_enter])

print "value:",number
3 голосов
/ 29 мая 2009

Насколько надежен ваш формат? Если разделитель всегда точно равен «:», работает следующее. Если нет, то сравнительно простое регулярное выражение должно делать эту работу.

Пока вы работаете с довольно простыми типами переменных, функция eval в Python делает сохранение переменных в файлах удивительно простым.

(Ниже приведен словарь, кстати, который вы упомянули как одно из ваших предпочтительных решений).

def read_config(filename):
    f = open(filename)
    config_dict = {}
    for lines in f:
        items = lines.split(': ', 1)
        config_dict[items[0]] = eval(items[1])
    return config_dict
1 голос
/ 29 мая 2009

То, что вы хотите получить, это следующее, но это НЕ РЕКОМЕНДУЕТСЯ :

>>> for line in open('dangerous.txt'):
...     exec('%s = %s' % tuple(line.split(':', 1)))
... 
>>> var_a
'home'

Это создает поведение, похожее на PHP register_globals, и, следовательно, имеет те же проблемы безопасности. Кроме того, использование exec, которое я показал, позволяет выполнять произвольный код. Только используйте это, если вы абсолютно уверены, что содержимому текстового файла можно доверять при любых обстоятельствах.

Вам действительно следует рассмотреть возможность связывания переменных не с локальной областью, а с объектом, и использовать библиотеку, которая анализирует содержимое файла так, что код не выполняется. Итак: используйте любое другое решение, представленное здесь.

(Обратите внимание: я добавил этот ответ не как решение, а как явное не решение .)

0 голосов
/ 20 февраля 2016

Ответ hbn не будет работать "из коробки", если файл для загрузки находится в подкаталоге или с черточками .

В таком случае вы можете рассмотреть эту альтернативу:

exec open(myconfig.py).read()

Или проще, но не рекомендуется в python3:

execfile(myconfig.py)

Полагаю, предупреждение Stephan202 относится к обоим вариантам, и, возможно, цикл в строках безопаснее.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...