Megmutatjuk, hogy önálló Python scriptek hogyan kezelik a bemeneti paramétereiket és hogyan tudunk fájlokat írni és olvasni
A Python - ahogyan a legtöbb programnyelv - a fájlokat egy fájl objektumon keresztül olvassa és írja. Nézzük meg, hogy hogyan működik!
Az open(filename[, mode])
függvény egy fájlobjektumot ad vissza, ahol a mode
lehet 'r'
(olvasás), 'w'
(írás), 'r+'
(mindkettő), vagy bináris fájlokra 'rb'
, 'wb'
, 'r+b'
.
f = open('E0.csv') # megnyitja olvasasra, visszaad egy file-objektumot
print f
Egyelőre ez csak egy fájl objektum. A mintafájlunk az angol Premier League 2015/16-os idényének a statisztikáit tartalmazza. Most olvassunk is valamit! Az f.read()
kiolvassa a fájlt teljes tartalmát egy sztringbe. Nem printeljük ki az egészet, mert túl sok.
f = open('E0.csv')
content = f.read()
print content[:100]
Olvassuk ki most csak az első sort!
f = open('E0.csv')
first_line = f.readline()
print first_line
second_line = f.readline()
print second_line
Ez még mindig nagyon fárasztó. De szerencsére a fájl objektum iterálható, soronként.
Figyeljük meg, hogy újsor karakter van minden sor végén.
f = open('E0.csv')
L = []
for line in f:
L.append(line)
print L[:10]
Az L
lista a fájl sorait tartalmazza. A sorokat .split(",")
-tel cellákká is tudjuk tördelni, de erről mindjárt részletesebben.
Képzeljük el, hogy Liverpool szurkolók vagyunk és nekünk csak a kedvenc csapatunk eredményei számítanak. Írjuk ki egy fájlba őket! Az olvasáshoz hasonlóan szükségünk lesz egy fájl objektumra, de ahhoz, hogy írni tudjuk, másként kell megnyitni. Először egy egyszerű példa. Az open(filename, 'w')
írásra nyitja meg a fájlt, de ha írunk, vigyázzunk, hogy zárjuk is be!
f = open('Liverpool.csv', 'w')
f.write('YNWA')
f.close()
Megjegyzés: szöveges fájl olvasásához az open('E0.csv', 'r')
parancsot használjuk, de alapértelmezésben olvasásra nyitunk meg egy fájlt, ezért az r
elhagyható.
Térjünk vissza az eredeti példához! Soronként beolvassuk a fájlt, és azt a sort, ahol a Liverpool szerepel, elmentjük. Ne felejtsük el, hogy a fejlécre továbbra is szükségünk van!
f = open('E0.csv')
L = [f.readline()]
for line in f:
if 'Liverpool' in line:
L.append(line)
with open('Liverpool.csv', 'w') as f:
for l in L:
f.write(l)
f.close()
Figyeljük meg, hogy a write metódus nem tesz automatikusan újsort a kiírandó szöveg végére, manuálisan kell az újsor karaterről gondoskodni.
A with open(filename, 'r') as f
pontosan ugyanahhoz az eredményhez vezet mintha f = open(filename, 'r')
-t írtunk volna,
de a block végén a fájlt be is zárja, így pontosan lehet szabályozni, hogy (legfeljebb) meddig álljon nyitva a fájl.
Ez írásnál (is) garantálja, hogy ne maradjon nyitva a fájl.
Ha lehet, használjuk az előbbit, így pontosan látjuk, meddig olvassuk a fájlunkat és biztonságosabb a fájl korrupcióval szemben is (adat-meghibásodás)!
csv
és json
python-ban¶Az előző fájl .csv
kiterjesztése a comma separated values-ra utal. Az ilyen fájlokban egy sorban egy rekord szerepel, a rekordok adatait pedig vesszővel -- választhatunk más karaktert pl. tab, pontosvessző stb. -- választjuk el. Pythonnal könnyű kezelni az ilyen fájlokat. Erre való a csv
modul.
import csv
L=[]
with open('E0.csv', 'rb') as csvfile:
reader = csv.reader(csvfile, delimiter=',', quotechar='"')
for row in reader:
L.append(row)
print L[0]
print L[19]
A különbség szembetűnő. A csv.reader
egyből listát csinál nekünk a sorokból. Ráadásul megadhatjuk neki az elválasztó karaktert, valamint a quotechar
-t is, ami az idézőjel karaktert jelöli ki. Ez azért fontos néhány esetben, mert sokszor számok és sztringek vegyesen vannak egy csv fájlban, ilyenkor a sztringeket idézőjelbe szokták tenni, amit a csv
modul felismer és nem nekünk kell foglalkozni vele.
.csv
fájlt binárisként nyissuk meg (rb
/wb
), a csv
modul így fogja jól kezelni.
Általában nem baj ha mindig (szövegfájlt is) binárisként kezelünk, fordítva lehet nagyobb probléma, de bővebben a sorvége karakterről. Ez az oprendszerek eltérő sorvége kezelése miatt alakult így.
Ha jól megnézzük az adatokat, nekünk nem feltétlenül listákra lenne szükségünk, hanem szótárakra. A fájl ugyanis minden meccsre ugyanazokat az adatokat tárolja, mi pedig szívesebben hivatkozunk indexek helyett nevekkel dolgokra. Erre is van lehetőség.
import csv
L=[]
with open('E0.csv', 'rb') as csvfile:
reader = csv.DictReader(csvfile)
for row in reader:
L.append(row)
print L[0]
print L[1]
Tároljuk most el a Liverpool mérkőzéseinek legfontosabb adatait. Ezek a 'Date', 'HomeTeam', 'AwayTeam', 'FTHG'(Full Time Home Goals), 'FTAG' (Full Time Away Goals), 'FTR' (Full Time Result)! A tároláshoz a csv.DictWriter
lesz segítségünkre. a writer.writeheader()
a fejlécet írja ki fájlba, a writer.writerows()
pedig egy mozdulattal kiírja az összes adatunkat. A fieldnames
paraméterben adhatjuk meg, hogy milyen attribútumokra van szükségünk, az extrasaction='ignore'
pedig pusztán azért kell, hogy a többi adatot ne írja bele.
import csv
L=[]
with open('E0.csv', 'rb') as csvfile:
reader = csv.DictReader(csvfile)
for x in reader:
if x['HomeTeam'] == 'Liverpool' or x['AwayTeam'] == 'Liverpool':
L.append(x)
csvfile.close()
with open('Liverpool.csv', 'wb') as output:
fields = ['Date', 'HomeTeam', 'AwayTeam', 'FTHG', 'FTAG', 'FTR']
writer = csv.DictWriter(output, fieldnames=fields, extrasaction='ignore')
writer.writeheader()
writer.writerows(L)
output.close()
JavaScript Object Notation
Tárolhatunk benne számokat, sztringeket, listát, szótárat. Sőt, tetszőlegesen egymásba ágyazhatunk szótárakat, listákat, listák listáját, szótárak listáját, szótárak szótárát, listák szótárát. Listák elemeit vesszővel választjuk el, a szótárakat pedig mint a Pythonban key:value
módon adjuk meg.
{
"Liverpool" : {
"Players": [
"Steven Gerrard",
"Bill Shankly"
],
"Results" : [
{
"HomeTeam":"Liverpool",
"AwayTeam":"Tottenham",
"HTG":1,
"ATG":1
},
{
"HomeTeam":"West Ham",
"AwayTeam":"Liverpool",
"HTG":2,
"ATG":0
}
],
"Points":1,
"Goals Scored":1,
"Goals Condceded":3
}
}
Természetesen a Pythonnal a json-t is kényelmesen lehet kezelni. Egyszerűen beolvassuk a fájlt és kiírjuk a képernyőre. Látjuk, hogy Python szótár keletkezett belőle, tehát hivatkozhatunk a kulcsaira. Az u'Steven Gerrard'
azt jelenti, hogy unicode sztringet olvastunk be (karakterkódolás).
import json
with open('Liverpool.json') as data_file:
data = json.load(data_file)
print data
print data['Liverpool']['Players']
Írjuk ki egy fájlba a meccsek eredményeit! A külalakra is figyelünk, erre való a sort_keys
, az indent
és a separators
. A json.dumps(obj)
tetszőleges Python objectet json sztringgé alakít, így ezt egyszerűen kiírjuk a fájlba!
import json
with open('Liverpool.json') as data_file:
data = json.load(data_file)
data_file.close()
with open('Liverpool_matches.json', 'wb') as f:
f.write(json.dumps(data['Liverpool']['Results'],
sort_keys=True, indent=4, separators=(',', ': ')))
json.dump(JSON_formaju_szoveg, file)
: kiírás fájlba
json.dumps(objektum)
: objektum JSON formátumúvá konvertálása
json.load(file)
: a file-ban lévő JSON formátumú dokumentumot Python objektummá konvertál
json.loads(JSON_formaju_szoveg)
: JSON formátumú dokumentumot Python objektummá konvertál
Részletek a https://docs.python.org/2/library/json.html.
Szeretnénk a Python programunknak kívülről átadni paraméterértékeket!
Elmentünk .py
végződéssel egy fájlt. Ezt vagy a rendszer felismeri mint Python scriptet vagy megfelelő paranccsal indítjuk. Első programunkkal kiírjuk a bemeneti paraméterek számát és listáját. Az első elem mindig a script neve. A paramétereket a sys.argv
listában tárolja a Python. Ehhez kell az import sys
csomag betöltése. Minden argumentum karakterlánc (list
of str
).
A következő kódot írjuk ki egy fájlba, és futassuk parancssorból a megfelelő paranccsal.
import sys
print 'Az argumentumok szama: ', len(sys.argv)
print 'Az argumentumok listaja:', str(sys.argv)
! python parancssori.py arg1 arg2
A !
jelzi, hogy azt a cellát parancssorba futtassa a notebook.
Az ilyen paramétereket hívjuk pozicionális paramétereknek, hiszen a sys.argv
listában elfoglalt helyük alapján azonosítjük őket.
Feladat: emeljünk egy számot adott hatványra! Ha az alap és a kitevő is egész, akkor számoljuk a hatványt egészek hatványaként, különben lebegőpontosként. A két számot parancssori argumentumként adjuk át a programnak.
A következő kódot másoljuk egy fájlba és parancssorból futtassuk!
import sys
def is_intstring(s):
try:
int(s)
return True
except ValueError:
return False
a = []
for i in range(1,3):
if is_intstring(sys.argv[i]):
a.append(int(sys.argv[i]))
else:
a.append(float(sys.argv[i]))
print a[0] ** a[1]
A futtatások eredményei:
! python hatvany.py 4.2 3
!python hatvany.py 2 100
A sys.argv
tömböt is feldolgozhatjuk, de ezt is megtette helyettünk már valaki. Az argparse
modul segít nekünk egészen összetett parancssori argumentumok beolvasásában is. Nézzünk példát egy flag-re. Ezek kvázi kétállapotú kapcsolók, amelyek befolyásolják a kód működését, nézzünk egy példát a verbosity-re. Ha a felhasználó szeretné, követheti a lépéseket.
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("--verbosity", help="increase output verbosity")
args = parser.parse_args()
print type(args.verbosity)
if args.verbosity:
print "verbosity turned on"
else:
print "verbosity turned off"
!python parser.py --verbosity 1
!python parser.py
Ez minden egész értéket elfogad a --verbosity
után. Még ennél is elegánsabb az action='store_true'
. Most ráadásul elég csak -v
-vel meghívni.
A lehetséges argumentumokról bővebben itt: https://docs.python.org/2/library/argparse.html
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("-v", "--verbose", help="increase output verbosity", action="store_true")
args = parser.parse_args()
print type(args.verbose)
if args.verbose:
print "verbosity turned on"
else:
print "verbosity turned off"
!python parser2.py
!python parser2.py --verbose
!python parser2.py -v
Sőt, a help menü automatikusan elkészül. Ehhez kellett a help="increase output verbosity"
.
!python parser2.py --help
Vissza a csv fájlunkhoz. Szeretnénk megtudni, hogy egy adott csapatnak hány olyan mérkőzése volt, amelyen legalább x
gólt rúgott. A csapat nevét és a gólok számát is olvassuk be a parancssorból! Az action='store'
az args
szótár megdelelő kulcsához társítja az értéket, a type
pedig meghatározza a típusát. Megjegyezzük, hogy ezek az argumentumok opcionálisak, így nem árt, ha alapértelmezett értéke is van (default
).
import argparse
import csv
parser = argparse.ArgumentParser()
parser.add_argument("-t", "--team", help="The team we are looking for", action="store", type=str, default='Liverpool')
parser.add_argument("-g", "--goals", help="Number of minimum goals scored", action="store", type=float, default=0)
args = parser.parse_args()
m = 0
team = args.team
goals = args.goals
with open('E0.csv', 'rb') as csvfile:
reader = csv.DictReader(csvfile)
for x in reader:
if x['HomeTeam'] == team and float(x['FTHG']) >= goals:
m += 1
elif x['AwayTeam'] == team and float(x['FTAG']) >= goals:
m += 1
print m
!python goals.py -h
!python goals.py -g 1