web-dev-qa-db-fra.com

Meilleure façon de récupérer les valeurs de variables d'un fichier texte - Python - Json

En se référant à cette question , j'ai un problème similaire - mais pas le même -.

En chemin, je vais avoir un fichier texte structuré comme suit:

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

Et j'ai besoin que ce python lise le fichier puis crée une variable nommée var_a avec la valeur 'home', etc.

Exemple:

#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.

Est-ce possible, je veux dire, même garder le type var?

Notez que j'ai la liberté totale quant à la structure du fichier texte. Je peux utiliser le format qui me convient si celui que je propose n'est pas le meilleur.

EDIT: ConfigParser peut être une solution, mais je ne l'aime pas trop car, dans mon script, je devrai ensuite faire référence aux variables du fichier avec

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

Mais ce que j'adorerai, c’est de me référer directement à la variable, comme je l’ai déclaré dans le script python ...

Il existe un moyen d'importer le fichier en tant que dictionnaire python?

Oh, dernière chose, gardez à l’esprit que je ne sais pas exactement combien de variables aurais-je dans le fichier texte?.

Edit 2: La solution JSON de stephan m'intéresse beaucoup, car le fichier texte pourrait ainsi être lu simplement avec d'autres langages (PHP, puis via JavaScript AJAX, par exemple), mais j'échoue. dans quelque chose en agissant cette solution:

#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'

Dans quels types de problèmes puis-je tomber avec le format JSON? Et comment puis-je lire un tableau JSON dans un fichier texte et le transformer en un dict en python?

P.S: Je n'aime pas la solution utilisant des fichiers .py; Je préférerai .txt, .inc, .qui n’est pas restrictif pour une langue.

34
Strae

Chargez votre fichier avec JSON ou PyYAML dans un dictionnaire the_dict (voir la documentation sur JSON ou PyYAML pour cette étape, les deux peuvent stocker le type de données) et ajoutez le dictionnaire à votre dictionnaire de globaux, par exemple. en utilisant globals().update(the_dict).

Si vous le préférez dans un dictionnaire local (par exemple, dans une fonction), procédez comme suit:

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

tant qu'il est sécuritaire d'utiliser exec. Sinon, vous pouvez utiliser le dictionnaire directement.

14
stephan

Mais ce que je vais aimer, c’est de me référer à la variable direclty, telle que je l’ai déclarée dans le script python.

En supposant que vous souhaitiez modifier légèrement votre syntaxe, utilisez simplement python et importez le module "config".

# myconfig.py:

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

Alors fais 

from myconfig import *

Et vous pouvez les référencer par leur nom dans votre contexte actuel.

59
hbn

Utilisez ConfigParser.

Votre config:

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

Votre code 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")
24
Igor Krivokon

Vous pouvez traiter votre fichier texte en tant que module Python et le charger dynamiquement à l'aide de imp.load_source :

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

Exemple:

// 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
...
18
Nick Dandoulakis

Les autres solutions publiées ici ne fonctionnaient pas pour moi car: 

  • j'ai juste besoin de paramètres d'un fichier pour un script normal
  • import * n'a pas fonctionné pour moi, car j'ai besoin d'un moyen de les remplacer en choisissant un autre fichier
  • Juste un fichier avec un dict n'était pas bien, car j'avais besoin de commentaires.

Donc, j'ai fini par utiliser Configparser et globals().update()

Fichier de test:

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

#that neither

Et c'est mon script de démonstration:

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

C'est juste pour un fichier avec une section maintenant, mais ce sera facile à adopter.

J'espère que ce sera utile pour quelqu'un :)

5
SolarSimon

Supposons que vous ayez un fichier appelé "test.txt" avec:

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

Et vous voulez trouver une variable (a, b, c, d ou 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
4
JorgeGarza

Quelle est la fiabilité de votre format? Si le séparateur est toujours exactement ':', ce qui suit fonctionne. Sinon, une expression rationnelle relativement simple devrait faire l'affaire.

Tant que vous travaillez avec des types de variables assez simples, la fonction eval de Python facilite la persistance des variables dans les fichiers.

(Ce qui suit vous donne un dictionnaire, d'ailleurs, que vous avez mentionné était l'une de vos solutions préférées).

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
3
mavnn

Voici ce que vous souhaitez apparemment, mais ceci est NOT RECOMMENDED:

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

Cela crée un comportement quelque peu similaire à celui de register_globals et pose donc les mêmes problèmes de sécurité. De plus, l'utilisation de exec que j'ai montré permet l'exécution de code arbitraire. Only utilisez cette option si vous êtes absolument certain que le contenu du fichier texte peut être approuvé en toutes circonstances.

Vous devriez vraiment envisager de lier les variables non à la portée locale, mais à un objet, et utiliser une bibliothèque qui analyse le contenu du fichier de sorte qu'aucun code ne soit exécuté. Alors: allez avec l'une des autres solutions fournies ici.

(Remarque: j'ai ajouté cette réponse non pas en tant que solution, mais en tant que non-solution explicite.)

1
Stephan202

la réponse de hbn ne fonctionnera pas si le fichier à charger se trouve dans un sous-répertoire ou est nommé avec des tirets .

Dans un tel cas, vous pouvez envisager cette alternative:

exec open(myconfig.py).read()

Ou le plus simple mais déconseillé en python3:

execfile(myconfig.py)

Je suppose que l'avertissement de Stephan202 s'applique aux deux options, cependant, et peut-être que la boucle sur les lignes est plus sûre.

0