Python: Leggi file di configurazione con più linee per tasto
-
20-09-2019 - |
Domanda
Sto scrivendo una piccola suite di test DB, che legge i file di configurazione con le query e dei risultati attesi, per esempio:.
query = "SELECT * from cities WHERE name='Unknown';"
count = 0
level = 1
name = "Check for cities whose name should be null"
suggested_fix = "UPDATE cities SET name=NULL WHERE name='Unknown';"
Questo metodo funziona bene; Divido ogni riga usando string.partition('=')
di Python.
Il mio problema è query SQL molto lunghe. Attualmente, ho semplicemente incollare queste query come una battuta, che è brutta e impossibile da mantenere.
Vorrei trovare un elegante modo Pythonic di leggere il diritto di espressione, anche se si estende su molte linee.
Note:
- le mie query SQL potrebbero contenere il
=
- Non mi fantasia l'idea di costringere
"
s tutto il lato destro, perché ci sono molti file esistenti senza di essa.
Modifica
ConfigParser è grande, ma mi costringe a aggiungere uno spazio o una scheda alla All'inizio di ogni linea in una voce multilinea. Questo potrebbe essere un grande dolore.
Grazie in anticipo,
Adam
Soluzione
Questo è quasi esattamente la caso d'uso che ci ha fatto passare a YAML ( Wikipedia , python realizzazione , documentazione ; si potrebbe desiderare di guardare JSON come alternativa). YAML ha alcuni vantaggi rispetto configparser
o json
:
- leggibilità umana (meglio di JSON per i file più grandi);
- può serializzare oggetti Python arbitrari (che lo rende come non-sicuro come
pickle
, ma v'è una funzionesafe_load
nell'attuazione pitone per alleviare questo problema). Questo è già utile per qualcosa di semplice come un oggettodatetime
.
Per completezza, i principali svantaggi (IMO):
- implementazione di Python da un ordine di grandezza più lento di implementazione JSON;
- meno portabile su più piattaforme di JSON.
Ad esempio
import yaml
sql = """
query : "SELECT * from cities
WHERE name='Unknown';"
count : 0
level : 1
name : "Check for cities whose name should be null"
suggested_fix : "UPDATE cities SET name=NULL WHERE name='Unknown';"
"""
sql_dict = yaml.safe_load(sql)
print(sql_dict['query'])
stampe
SELECT * from cities WHERE name='Unknown';
Altri suggerimenti
Il modulo libreria standard di Python ConfigParser supporta questa per impostazione predefinita. Il file di configurazione deve essere in un formato standard:
[Long Section]
short: this is a normal line
long: this value continues
in the next line
Il file di configurazione di cui sopra potrebbe essere letto con il seguente codice:
import ConfigParser
config = ConfigParser.ConfigParser()
config.read('longsections.cfg')
long = config.get('Long Section', 'long')
Vorrei suggerire di usare un'espressione regolare ... Il codice potrebbe essere simile a questo per dare siete inizio:
import re
test="""query = "select * from cities;"
count = 0
multine_query = "select *
from cities
where name='unknown';"
"""
re_config = re.compile(r'^(\w+)\s*=\s*((?:".[^"]*")|(?:\d+))$', re.M)
for key, value in re_config.findall(test):
if value.startswith('"'):
value = value[1:-1]
else:
value = int(value)
print key, '=', repr(value)
L'output di questo esempio è:
~> python test.py
query = 'select * from cities;'
count = 0
multine_query = "select *\nfrom cities\n where name='unknown';"
Speranza che aiuta!
Saluti, Christoph