issuepy02 hu

43

Upload: blind-man

Post on 16-Apr-2015

35 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: IssuePY02 Hu

full circle magazin Python 2. kötet tartalom ^1A Full Circle magazin nem azonosítandó a Canonical Ltd.-vel

AZ UBUNTU LINUX KÖZÖSSÉG FÜGGETLEN MAGAZINJA

full circleProgramozói sorozat - Különkiadás

Programozóisorozat

Különkiadás

PROGRAMOZZUNKPYTHONBAN2. Kötet

Page 2: IssuePY02 Hu

full circle magazin Python 2. kötet tartalom ^2

Programozzunk Pythonban9. rész 3. oldal

Minden szöveg- és képanyag, amelyet a magazin tartalmaz, a Creative Commons Nevezd meg! ‒ Így add tovább! 2.5 Magyarország Licenc alattkerül kiadásra. Ez annyit jelent, hogy átdolgozhatod, másolhatod, terjesztheted és továbbadhatod a benne található cikkeket a következő feltéte-lekkel : jelezned kel l eme szándékodat a szerzőnek (legalább egy név, e-mai l cím vagy url eléréssel) valamint fel kel l tüntetni a magazin nevét

(ful l circle magazin) és az url-t, ami a www.ful lcirclemagazine.org (úgy terjeszd a cikkeket, hogy ne sugalmazzák azt, hogy te készítetted őket vagy a te munkád vanbenne). Ha módosítasz, vagy valamit átdolgozol benne, akkor a munkád eredményét ugyani lyen, hasonló vagy ezzel kompatibi l is l icenc alatt leszel köteles terjeszteni .A Full Circle magazin teljesen független a Canonical-tól, az Ubuntu projektek támogatójától. A magazinban megjelenő vélemények ésállásfoglalások a Canonical jóváhagyása nélkül jelennek meg.

Programozzunk Pythonban1 0. rész 7. oldal

Full CircleAZ UBUNTU LINUX KÖZÖSSÉG FÜGGETLEN MAGAZINJA

Programozzunk Pythonban1 1 . rész 1 2. oldal

Programozzunk Pythonban1 2. rész 1 7. oldal

Programozzunk Pythonban1 3. rész 22. oldal

Programozzunk Pythonban1 4. rész 27. oldal

Programozzunk Pythonban1 5. rész 34. oldal

Programozzunk Pythonban1 6. rész 39. oldal

A Full Circle magazin különkiadása

Üdvözöllek egy újabb, „egyetlen témárólszóló különkiadásban”

Válaszul az olvasók igényeire, néhány sorozatként megírt cikktartalmát összegyűjtjük dedikált kiadásokba.

Most ez a „Programozzunk Pythonban” 9.-1 6. részének azújabb kiadása (a magazin 35.-42. számaiból) , semmi extra,csak a tények.

Kérlek, ne feledkezz meg az eredeti kiadási dátumról. Ahardver és szoftver jelenlegi verziói eltérhetnek az akkorközöltektől, így ellenőrizd a hardvered és szoftvered verzióit,mielőtt megpróbálod emulálni/utánozni a különkiadásokbanlévő ismertetőket. Előfordulhat, hogy a szoftver későbbiverziói vannak meg neked, vagy érhetők el a kiadásodtárolóiban.

Jó szórakozást!

Page 3: IssuePY02 Hu

full circle magazin Python 2. kötet tartalom ^3

HogyanokÍrta: Greg Walters

Programozzunk Pythonban - 9. részElőző részek:FCM 27. -34. számokbanaz 1. -8. részek

Itt használható:

Kategóriák:

Eszközök:

GrafikaFej lesztés Internet M/média Rendszer

MerevlemezCD/DVD USB eszköz Laptop Vezetéknélkül i

Ha olyan vagy mint én,akkor számítógépedente is mp3 formátum-ban tárolod kedvenc

zenéidet. Amikor kevesebb, mint1000 számod van, akkor mégelég könnyű megjegyezned,hogy mi és hol van. Mivel régeb-ben DJ voltam és zenéim nagyrészét átkonvertáltam, ezért ne-kem ennél jóval több MP3-amvan. Régebben a legnagyobbproblémát a merevlemez kapa-citása jelentette számomra.Azonban manapság a legfruszt-

rálóbb dolog, hogy nem tudomészben tartani , hogy mim éshol van.

Ebben a leckében megnéz-zük, hogy hogyan tudunk létre-hozni az MP3-ainknak egy kata-lógust. Megismerkedünk né-hány újabb python koncepció-val , amel lett, hogy felfrissítjükaz adatbázisokról szerzett tu-dásunkat is.

Először, nem árt tudnunkarról , hogy egy MP3 fáj l tartal-mazhat önmagáról információ-kat. I lyen adat a dal címe, albu-ma, szerzője, stb. Ezek az infor-mációk az ID3 elemekben he-lyezkednek el , amit meta-adat-nak is szoktunk hívni . Az elsőidőkben egy MP3 fáj lban csakigen korlátozott információ-mennyiség volt eltárolható. Ezeredeti leg a fáj l legutolsó 128bájtjában foglalt helyet. Mivelennek a blokknak igen kicsivolt a mérete, ezért csak 30karakter hosszú lehetett a dalcíme, szerzőjének neve, stb.Sok zenefáj l számára ennyiéppen elegendő volt, de (és ez

az egyik örök kedvenc szá-mom) ha például a „Clowns(The Demise of the EuropeanCircus with No Thanks toFel l ini )” számról volt szó, akkorcsak az első 30 karakter voltmeg a címből . Ez NAGYONfrusztrálólag hatott igen sokemberre. A „sztenderd” ID3-aselem egy idő után ID3v1-kéntlett ismert, miután bevezettekegy új formátumot, amit –meglepő módon - ID3v2-nekneveztek el . Ez az új formátumlehetővé tette változó hosszú-ságú adatok tárolását a fáj lelején, amel lett, hogy a régiID3v1 meta-adat - a régebbitípusú lejátszók miatt - mégmindig helyet kapott a fáj l vé-gén. Most már 256 Mb-nyimeta-adatot is eltárolhattunk.Ez pont ideál is volt a rádióál lo-mások és az olyan őrültek szá-mára, mint ami lyen én is va-gyok. Az ID3v2 rendszer alattminden egyes adatcsoport egyframe-ben (szelet) kap helyet,és mindegyik i lyen frame-nekvan egy azonosítója. A koraiID3v2-ben ez az azonosító há-rom karakter hosszú volt. A

jelenlegi verzió (ID3v2.4) márnégy karakterest használ .

Régen egyszerűen binárisolvasás módban megnyitottukvolna a fáj lt, és addig kutakod-tunk volna benne, amíg megnem találtuk a keresett infor-mációt. Mivel nem voltaksztenderd könyvtáraink, amikezt lekezelték volna, ezért eztigen sok munka volt megcsi-nálni . Szerencsére, mostanraezek már rendelkezésünkreál lnak. Mi itt a Mutagen nevűprojektet fogjuk használni .Menjünk is a Synapticba éstelepítsük a python-mutagent.Ha szeretnénk, akkor itt egykeresést is lefuttathatunk az„ID3”-ra. Azt fogjuk tapasztalni ,hogy több mint 90 csomagotdob ki eredményül (Karmic-ban), majd, ha a „Python” szótis begépel jük a gyorskeresőmezőbe, akkor nyolc csomagottalálunk. Mindegyik mel lettszólnak érvek és el lenérvek, demostani projektünkhöz a Muta-gent fogjuk választani . Nyu-godtan beleáshatjuk magunkata többibe is kiegészítő tanulás

Page 4: IssuePY02 Hu

full circle magazin Python 2. kötet tartalom ^4

Programozzunk Pythonban ‐ 9. részcél jából .

Most, hogy már fel van tele-pítve a Mutagen, elkezdhetünkkódolni .

Indul junk egy „mCat” nevűprojekt készítésével . Ezutánjöhetnek az importja ink.

from mutagen.mp3 import MP3

import os

from os.path import

join,getsize,exists

import sys

import apsw

Ezekkel többnyire már talál -koztunk. Ezt követően létre sze-retnénk hozni a függvény dek-larációinkat.

def MakeDataBase():

pass

def S2HMS(t):

pass

def WalkThePath(musicpath):

pass

def error(message):

pass

def main():

pass

def usage():

pass

ÁÁÁ. . . i tt valami új dologvan. Készen vagyunk a main ésa usage metódusokkal . Mirelesznek ezek jók? Mielőtt meg-beszélnénk őket, helyezzünk elmég egy dolgot.

if __name__ == '__main__':

main()

Mi a fene ez? Ezzel a trükkelazt érjük el , hogy a fáj lunkat ké-pesek leszünk különál ló alkal-mazásként, i l letve újrahasznál-ható modulként egy másikprogramba beimportálva ishasználni . Gyakorlati lag aztmondja ki , hogy „HA ez a fáj l afő alkalmazás, akkor a mainrutin meghívásával tudjuk fut-tatni , különben közvetlenül egykiegészítő modulként fogunk

hivatkozni a metódusaira egymásik programból”.

Ezután, fogalmazzuk meg ausage függvényt. Lent látható ausage rutin tel jes kódja.

I tt fogjuk létrehozni a fel-használó számára megjelenőüzenetet, mely akkor jelenikmeg, amikor nem megfelelőparaméterekkel indítják el aprogramunkat. Figyel jük meg,hogy a „\n” kifejezést egy újsor, a „\t”-t egy tab kiíratásá-hoz használ juk. Ezeken felülhasznál juk még a „%s”-t azalkalmazás nevének bekéré-séhez, mely a sys.argv[0]-banvan eltárolva. Ezután meghív-juk az error rutint a „message”kiíratásához, majd a sys.exit(1)-

el ki lépünk az alkalmazásból .

Ha ezzel készen vagyunk,akkor készítsük el az errorrutint. I tt van a tel jes kódja:

def error(message):

print >> sys.stderr,

str(message)

Egy átirányításnak nevezettdolgot alkalmazunk (a „>>”).Amikor a print-et hívjuk, való-jában arra utasítjuk a Pythont,hogy írassa vagy streamel je kia sztenderd kimenetre a mega-dott paramétereket, ami leg-többször az éppen futó termi-nált jelenti . Ennek eléréséhez(a színfalak mögött) az stdoutothasznál juk. Amikor hibaüzene-tekkel dolgozunk, akkor az

def usage():

message = (

'==============================================\n'

'mCat ­ Finds all *.mp3 files in a given folder (and sub­folders),\n'

'\tread the id3 tags, and write that information to a SQLite database.\n\n'

'Usage:\n'

'\t{0} <foldername>\n'

'\t WHERE <foldername> is the path to your MP3 files.\n\n'

'Author: Greg Walters\n'

'For Full Circle Magazine\n'

'==============================================\n'

).format(sys.argv[0])

error(message)

sys.exit(1)

Page 5: IssuePY02 Hu

full circle magazin Python 2. kötet tartalom ^5

Programozzunk Pythonban ‐ 9. rész

stderrt szoktuk megadni . Mi isezt tesszük: átirányítjuk a printkimenetét az stderr folyamra.

Most dolgozzunk egy kicsit amain függvényen. Itt fogjuk be-ál l ítani az adatbázis kapcsolatotés kurzort, majd vetünk egy pi l -lantást a parancssori paraméte-rekre. Ha minden klappol , akkor

meghívjuk a saját függvénye-inket az igazi munka elvégzé-séhez. A kód fentebb látható.

Mint ahogy múltkor, most islétrehozunk két globál is válto-zót, melyeket az adatbáziskeze-léshez használunk. Ezeket con-nection-nek és cursor-nakhívjuk. Ezután megnézzük a

parancssorból kapott paramé-tereket (ha vannak egyáltalán).Mindezt a sys.argv utasítássaltesszük. Két paramétert kere-sünk: az első az alkalmazásneve, a második az MP3 fáj lokelérési útja. Ha nincs megmindkét paraméter, akkor meg-hívjuk a usage szubrutint, melykiíratja az előbb megírt üzene-tet és ki lép. Ha viszont meg-kaptuk mindkettőt, akkor az If-ünk else ágára ugrik a vezérlés.Ezt követően eltárol juk a ki in-duló útvonalat a StartFolderváltozóban. Arra azonbanügyelnünk kel l , hogy ha szóközvan az elérési útban - mintpéldául az (/mnt/musicmain/Adult Contemporary)-ben - aspace után következő karak-terek egy új paraméterkéntfognak értelmeződni . Ezért habármikor szóköz van az elérésiútban, akkor ne felejtsük el azegészet idézőjelek közé rakni .Következőnek beál l ítjuk a con-nectiont és a cursort, elkészít-jük az adatbázist, majd jön atényleges munka, amikor ismeghívjuk a WalkThePathrutint, majd lezárjuk a kapcsola-tot egy üzenet kiséretében, amitudatja a felhasználóval , hogykészen vagyunk. Itt van a

WalkThePath tel jes kódja:http: //pastebin.com/CegsAXjW.

Először kinul lázzuk azt a há-rom számlálót, melyekben amunka ál lapotát fogjuk követni .Ezután megnyitunk egy fáj lt,melyben az esetlegesen felme-rülő hibákat fogjuk loggolni . Eztkövetően, rekurzívan végigme-gyünk a felhasználó által mega-dott útvonalon. Gyakorlati lag amegadott útvonalban lévőmappákba lépegetünk be és ki ,miközben bármi lyen .mp3 kiter-jesztésű fáj l után kutatunk. Haezzel készen vagyunk, akkormegnövel jük a mappa és a fáj lszámlálóját, hogy tudjuk meny-nyi fáj lon vagyunk már túl . Havégeztünk, akkor átmegyünkminden fáj lon. Kinul lázunk min-den helyi változót, mely azadott számról tartalmaz infor-mációt. I tt használ juk azos.pathban lévő „join” függ-vényt, melyet a megfelelő elé-rési út és fáj lnév létrehozásá-hoz használunk. Ezt fogja meg-kapni a mutagen, amiből megtudja ál lapítani , hogy hol keres-se az adott fáj l t. Ezt követőenátadjuk a fáj lnevet az MP3osztálynak melyért az „audio”egy példányát kapjuk cserébe.

def main():

global connection

global cursor

#­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­

if len(sys.argv) != 2:

usage()

else:

StartFolder = sys.argv[1]

if not exists(StartFolder): # From os.path

print('Path {0} does not seem to

exist...Exiting.').format(StartFolder)

sys.exit(1)

else:

print('About to work {0}

folder(s):').format(StartFolder)

# Create the connection and cursor.

connection=apsw.Connection("mCat.db3")

cursor=connection.cursor()

# Make the database if it doesn't exist...

MakeDataBase()

# Do the actual work...

WalkThePath(StartFolder)

# Close the cursor and connection...

cursor.close()

connection.close()

# Let us know we are finished...

print("FINISHED!")

Page 6: IssuePY02 Hu

full circle magazin Python 2. kötet tartalom ^6

Programozzunk Pythonban ‐ 9. részHa elkészültünk, akkor kiszed-jük a fáj lból az összes ID3 ele-met és végiglépkedünk a l istán,olyan tagok után kutatva, ame-lyekre szükségünk van, majdezeket az ideiglenes változók-hoz rendel jük. Ezzel a módszer-rel minimal izál juk a lehetségeshibák számát. Vessünk egypi l lantást a kód azon részére,mely a számok sorszámát tárol-ja . Amikor ezt visszakapjuk amutagentől , akkor az lehet egyszám, egy „4/8”-hoz hasonlósztring vagy „_trk[0]” és„_trk[1]”, vagy akár semmi is. Atry/except vezérlési szerkezetetalkalmazzuk az olyan hibák el-kapásához, melyek emiatt elő-jöhetnek. Most nézzük meg arekordok kiírását. Egy kicsitmáshogy járunk el mint múlt-kor. Most is létrehozzuk az SQLutasítást, mint eddig, de a be-helyettesítendő értékek helyérea „?”-et írjuk. Az ASPW webhe-lye szerint ez egy biztonságo-sabb módszer. Nem fogok velükvitatkozni . A végén lekezelünkminden előforduló hibát. Leg-többször ezek a „TypeError”-okvagy „ValueError”-ok lesznek,melyeket a nem lekezelhetőUnicode karakterek okoznak.Ál l junk meg egy pi l lanatra asztring érdekes formázása és

kiíratása fölött. I tt nem használ-juk a „%” helyettesítő karak-tert. Helyette a „{0}” típushelyettesítést alkalmazzuk, amia Python 3.x specifikáció része.Az alapvető alakja az alábbi :

Print('String that will be

printed with {0} number of

statements”).format(replaceme

nt values)

Ezt az alapvető szintaxisthasznál juk az „efi le.writel ines”-nál is.

Végül nézzük meg az S2HMSmetódust. Ez a rutin a számhosszát kapja paraméterként,amely egy mutagen általvisszaadott lebegőpontos szám.Ezt fogjuk „Óra:Perc:Másod-perc” vagy „Perc:Másodperc”alakra átkonvertálni . Figyel jükmeg a return utasítást. Ismét aPython 3.x-ben bevezetett szin-taxist alkalmazzuk. Van azon-ban egy tel jesen új dolog is.Helyettesítési halmazokat hasz-nálunk (0, 1, és 3), de mi a„:02n” az 1-es és 2-es számután? Ez azt mondja ki , hogykét helyen szeretnénk csak be-vezető nul lákat látni . Tehát, haa dal mérete 2 perc 4 másod-perc, akkor a visszaadott karak-

terlánc „2:04” lesz és nem„2:4”.

A programunk tel jes kódja itttalá lható:http: //pastebin.com/rFf4Gm7E.

Ez minden mára. Egy kicsitrövidebb lett mint múltkor, detalán picit bonyolultabb is. Havan egy kis időnk, akkor nyu-godtan belevethetjük magunkata Mutagenbe, hátha találunkmég valami érdekeset. Biztosanörömmel fogjuk venni , hogyMP3 fáj lok kezelésénél többre isképes.

Greg Walters a RainyDay SolutionsKft. tulajdonosa, amely egy tanács-adó cég Aurorában, Coloradóban,Greg pedig 1 972 óta foglalkozikprogramozással. Szeret főzni, túráz-ni, zenét hallgatni, valamint a csa-ládjával tölteni a szabadidejét.

Page 7: IssuePY02 Hu

full circle magazin Python 2. kötet tartalom ^!

HogyanokÍrta: Greg Walters

Programozzunk Pythonban - 1 0. rész

Valószínűleg mindenkihal lotta már az XML ki-fejezést. Viszont nembiztos, hogy tudjuk, mi

is ez. E havi anyagunk témája azXML lesz. Célunk, hogy

- megismerjük az XML-t- megmutassuk, miként

kel l írni és olvasni XML fáj lokatsaját alkalmazásokban.

- felkészül jünk a következőalkalomra tartogatott viszonylagnagy XML projektre.

Nos. . . Beszél jünk az XML-ről .A HTML-hez hasonlóan, az XMLis egy mozaikszó, ami az eX-tensible Markup Language rövi-dítése. Az adatok hatékony tá-rolására és interneten, vagymás kommunikációs hálózatonvaló továbbítására találták ki .Gyakorlati lag az XML egy szö-veges fáj l , ami a saját „tag”-ja ink (avagy elemeink) általvan formázva, így elég öndoku-mentáló a felépítése. Mivel egyszöveges ál lományról van szó,össze lehet tömöríteni a gyor-sabb és könnyebb továbbítás-hoz. A HTML-lel el lentétben azXML önmagában nem képessemmire. Nem foglalkozik az-zal , hogy te hogyan akarod azadataidat elrendezni . Ahogy azimént mondtam, XML írásakornem kel l egy sor általános„tag”-ra hagyatkozni . Elkészít-hetjük a sajátja inkat is.

Nézzünk egy általános pél-dát XML fáj lra:

<root>

<node1>Data

Here</node1>

<node2

attribute=”something”>Node 2

data</node2>

<node3>

<node3sub1>more

data</node3sub1>

</node3>

</root>

Az első feltűnő dolog az in-dentálás. Gyakorlati lag csak azemberi fogyasztás megkönnyí-tése miatt van. Az XML ugyan-olyan jól lenne így is:

<root><node1>Data

Here</node1><node2

attribute=”something”>Node 2

data</node2><node3><node3sub

1>more

data</node3sub1></node3></ro

ot>

A „<>” csúcsos zárójelekközött lévő tagokra van néhányelőírás. Először is, csak egyet-len szóból ál lhatnak. Másod-szor, amikor van egy nyitó tag-od (pl . <root>), akkor kel l vala-hol lennie egy ugyanolyan zárótagnak is. A záró elem egy „/”jel lel kezdődik. A tagok is mé-retérzékenyek: a <node>,<Node> és <NodE> mind kü-lönböző elemet jelöl , amikhezmegegyező zárótagnak KELL

tartoznia. Az elemnevek tartal-mazhatnak betűket, számokatés egyéb karaktereket is, denem kezdődhetnek számmalvagy központozással . A „-”, „ . ”és „: ” jeleket a nevekben lehe-tőleg kerül jük el , mivel néhányalkalmazás parancsnak, vagyobjektum adattagnak tekinthetiőket. Továbbá a kettőspontok-nak is valami más szerepükvan.

Minden XML fáj l a lapvetőenegy fa is - a gyökértől ki indulvaszétágazik. Minden XML ál lo-mánynak tartalmaznia KELLegy gyökér elemet, ami min-den más elemnek az őse. Ves-sünk ismét egy pi l lantást a pél-dánkra. A root alatt háromgyermek elemünk van (node1,node2, node3). A root elem le-származottai közti kapcsolat-hoz hasonlóan, a node3 is anode3sub1-nek a szülője.

Figyel jük meg a node2-őt.Vegyük észre, hogy a szokásos,elemek közötti adatok mel lettvan még egy, tulajdonságnak(attribute) nevezett értéke is.

Előző részek:FCM 27. -35. számokbanaz 1. -9. részek

Itt használható:

Kategóriák:

Eszközök:

GrafikaFej lesztés Internet M/média Rendszer

MerevlemezCD/DVD USB eszköz Laptop Vezetéknélkül i

Page 8: IssuePY02 Hu

full circle magazin Python 2. kötet tartalom ^!

Programozzunk Pythonban ‐ 10. részManapság igen sok fej lesztőazonban elkerül i használatukat,mivel az elemek közötti érték-ként is épp elég hatékonyaklesznek, ezen felül kevesebbpepecseléssel is jár nélkülözé-sük. Ennek el lenére látni fogjuk,hogy még mindig használ jákőket. Egy kicsit később mégkitérünk rájuk.

Nézzünk most meg egyhasznos példát (balra lent).

I tt a gyökérelem a „people”(emberek), melynek két gyer-meke van, „person” (személy)néven. Minden personnek vanhat leszármazottja: firstname(keresztnév), lastname (veze-

téknév), gender (nem), address(cím), city (város) és state (ál-lam). Első pi l lantásra azt hinnéaz ember, hogy ez egy adatbá-zis (gondol junk vissza az utóbbinéhány cikkre), és nem is té-vednénk nagyot. Ami azt i l leti ,néhány alkalmazás XML fáj lokathasznál egyszerű adatbáziske-zelésre is. Az XML-eket olvasóalkalmazások megírása vi-szonylag egyszerűen megold-ható. Csak nyissuk meg a fáj lt,olvassunk be minden sort, majdaz elem típusa szerint foglal -kozzunk a beolvasott sorokkal ,végül zárjuk le a fáj l t. Minda-zonáltal ennél vannak kifino-multabb megoldások is.

A soron következő példákbanegy ElementTree-nek nevezettkönyvtár modult fogunk hasz-nálni . A Synapticból közvetlenülfel lehet telepíteni a python-elementtree csomaggal . Énviszont inkább az ElementTreeweblapjáról töltöttem le aforrást (elementtree-1.2 .6-20050316.tar.gz):(http: //effbot.org/downloads/#elementtree). Amint lejött, a cso-magkezelővel kitömörítettemegy ideiglenes mappába. Miu-tán ebbe beleléptem, végrehaj-tottam a „sudopython setup.pyinstal l” utasítást.Ezzel a fáj lok bemá-solódtak a pythonközös mappájába,hogy python 2.5-ből ,vagy 2.6-ból hasz-nálni lehessen őket.Most már elkezdhe-tünk dolgozni . Hoz-zunk létre egy újmappát ehavi kó-dunknak, és ked-venc szövegszer-kesztőnket használ-va, másol juk ebbe afenti XML adatot,majd mentsük el„xmlsample1.xml"néven.

Ami a kódunkat i l leti , az elsődolog, amit meg kel l tennünk,hogy leel lenőrizzük az Element-Tree telepítést. I tt a kód:

import

elementtree.ElementTree as ET

tree =

ET.parse('xmlsample1.xml')

ET.dump(tree)

Amikor a tesztprogramotfuttatjuk, valami i lyesmit kel lenekapnunk:

<people>

<person>

<firstname>Samantha</firstname>

<lastname>Pharoh</lastname>

<gender>Female</gender>

<address>123 Main St.</address>

<city>Denver</city>

<state>Colorado</state>

</person>

<person>

<firstname>Steve</firstname>

<lastname>Levon</lastname>

<gender>Male</gender>

<address>332120 Arapahoe Blvd.</address>

<city>Denver</city>

<state>Colorado</state>

</person>

</people>

/usr/bin/python ­u

"/home/greg/Documents/articles/xml/read

er1.py"

<people>

<person>

<firstname>Samantha</firstname>

<lastname>Pharoh</lastname>

<gender>Female</gender>

<address>123 Main St.</address>

<city>Denver</city>

<state>Colorado</state>

</person>

<person>

<firstname>Steve</firstname>

<lastname>Levon</lastname>

<gender>Male</gender>

<address>332120 Arapahoe

Blvd.</address>

<city>Denver</city>

<state>Colorado</state>

</person>

</people>

Page 9: IssuePY02 Hu

full circle magazin Python 2. kötet tartalom ^9

Programozzunk Pythonban ‐ 10. részMindössze annyit csináltunk,

hogy megnyitottuk az Element-Tree-vel a fáj l t, a lapelemekre bon-tottuk a tartalmát, végül kiírattukúgy, ahogy az a memóriában van.Semmi különös.

Most cserél jük le az előbbikódot a következőre:

import

elementtree.ElementTree as ET

tree =

ET.parse('xmlsample1.xml')

person =

tree.findall('.//person')

for p in person:

for dat in p:

print "Element: %s ­

Data: %s" %(dat.tag,dat.text)

és futtassuk újra. Most i lyen ki-menetet kel lene kapjunk:

/usr/bin/python ­u

"/home/greg/Documents/article

s/xml/reader1.py"

Element: firstname ­ Data:

Samantha

Element: lastname ­ Data:

Pharoh

Element: gender ­ Data:

Female

Element: address ­ Data: 123

Main St.

Element: city ­ Data: Denver

Element: state ­ Data:

Colorado

Element: firstname ­ Data:

Steve

Element: lastname ­ Data:

Levon

Element: gender ­ Data: Male

Element: address ­ Data:

332120 Arapahoe Blvd.

Element: city ­ Data: Denver

Element: state ­ Data:

Colorado

Most már minden adat a tagneve mel lé került. Egyszerűencsak ki kel lett íratnunk az ered-ményt. Nézzük meg, hogy minkvan itt. Az ElementTree szét-bontotta a fáj l t egy tree nevűobjektumba. Ezután megkértük,hogy keresse meg a personösszes példányát. A használtpéldában csak kettő i lyen van,de ez a szám lehet egy, vagyakár ezer is. A person a people

leszármazottja, és tudjuk, hogya people egyszerűen egy gyö-kérelem. Az összes adatunk apersonba van elhelyezve. Lét-rehozunk egy for ciklust az ösz-szes person objektumon valóátlépegetésre. Ezután készítünkegy másik for ciklust az adatokpersononkénti kiszedéséhez,majd megjelenítjük az elem ne-vét (. tag) és adatát (. text).

Egy való életből vett példa:én és a családom egy Geo-caching nevezetű tevékenység-ben veszünk részt. Azoknak,akik esetleg nem tudnák, mi isez: egy „kocka” kincsvadászat,ami kézi GPS eszközöket hasz-nál valaki más által elrejtettdolgok felkutatásához. Az álta-

lános koordinátákat egy webla-pon helyezik el , néha egy-kétnyom kíséretében. Nekünk any-nyi a dolgunk, hogy bepötyög-jük a koordinátákat és megpró-bál juk megkeresni . A Wikipediaszerint több mint 1.000.000aktív geocache weblap van vi-lágszerte, köztük valószínűlegakad egy a környékeden is. Énkét weblapot használok célpon-tok kereséséhez. Az egyik ahttp: //www.geocaching.com/a másik pedig ahttp: //navicache.com/. Vannakmég mások is, de talán ez akettő a legnagyobb.

Mindegyik célpont informá-ciója egy alap XML fáj lban vaneltárolva. Vannak olyan alkal-

<?xml version="1.0" encoding="ISO­8859­1"?>

<loc version="1.0" src="NaviCache">

<waypoint>

<name id="N02CAC"><![CDATA[Take Goofy Pictures at Grapevine Lake by g_phillips

Open Cache: Unrestricted

Cache Type: Normal

Cache Size: Normal

Difficulty: 1.5

Terrain : 2.0]]></name>

<coord lat="32.9890166666667" lon="­97.0728833333333" />

<type>Geocache</type>

<link text="Cache Details">http://www.navicache.com/cgi­

bin/db/displaycache2.pl?CacheID=11436</link>

</waypoint>

</loc>Navicache fáj l

Page 10: IssuePY02 Hu

full circle magazin Python 2. kötet tartalom ^1 0

Programozzunk Pythonban ‐ 10. részmazások, melyek be tudják ol-vasni és átküldeni az adatokata GPS eszközre. Néhányukadatbázis-kezelő programkéntviselkedik - lehetőség van fi-gyelemmel kísérni tevékenysé-günket (néha) térképek segítsé-gével . Most még csak a letöl-tött fáj l szétbontására fogunkkoncentrálni .

A Navicachen találtam egynem túl régi texasi feladványt.Az előző oldal al ján látható.

Másol juk ki a fenti adatokatés mentsük el „Cache. loc” név-vel . Mielőtt nekiál lnánk kódolni ,vizsgál juk meg a rejtvény fáj l -ját.

Az első sor csak annyit mondnekünk, hogy ez egy val idáltXML fáj l . Ezt nyugodtan figyel-men kívül hagyhatjuk. A követ-kező sor (ami a „loc”-kal kezdő-dik) a gyökér, melynek version(verziószám) és src (forrás)tulajdonságai vannak. Emlék-szünk még, amikor korábbanazt mondtam, hogy néhányfáj lban találkozhatunk attribú-tumokkal? Lesznek még másokis ebben az ál lományban, a-hogy haladunk. Még egyszerelmondom, hogy a gyökér

ebben az esetben figyelmen kí-vül hagyható. A következő sor awaypoint (csomópont) gyer-mekelemet tartalmazza. (A cso-mópont ebben az esetben a rej-tekhely helyét jelenti . ) Ez egyszámunkra fontos adat lesz. I ttvan a rejtekhely neve, i l letveszélességi és hosszúsági koor-dinátái , a zsákmány típusa ésegy további információkat tar-talmazó honlap l inkje. A name(név) elem egy hosszú karak-terlánc, amiben van egy rakathasznos információ, de ehhezelőbb fel kel l bontanunk ma-gunknak. Készítsünk el egy újalkalmazást, ami beolvassa ésmegjeleníti ezt a fáj l t. Legyen aneve „readacache.py”. Kezdjükaz előző példabel i import ésparse utasításokkal .

import

elementtree.ElementTree as ET

tree = ET.parse('Cache.loc')

Egyelőre szeretnénk kiolvas-ni a waypoint tagban lévő ada-tokat. Ehhez az ElementTree.find függvényét használ juk. Azeredményt a „w” objektumbankapjuk vissza.

w = tree.find('.//waypoint')

Ezután át szeretnénk futni azösszes adaton. Egy for ciklustfogunk ehhez használni . A cik-lusban meg fogjuk nézni , hogya tag a „name”, „coord”, „type”és „l ink” közül melyik. Ettől füg-gően fogjuk kiszedni a bennelévő adatokat későbbi kiíratás-ra.

for w1 in w:

if w1.tag == "name":

Mivel először a „name” tagotkeressük, nem árt, ha megnéz-zük a beolvasandó adatokat.

<name

id="N02CAC"><![CDATA[Take

Goofy Pictures at Grapevine

Lake by g_phillips

Open Cache: Unrestricted

Cache Type: Normal

Cache Size: Normal

Difficulty: 1.5

Terrain : 2.0]]></name>

Ez egy igen hosszú sztring. Arejtekhely „id” (azonosító) egytulajdonság. A név a „CDATA”és „Open Cache:” közötti rész.Fel fogjuk darabolni ezt a sztrin-get további , nekünk megfelelőrészekre. Egy karakterlánc ré-szét az alábbi módon kapjukmeg:

newstring =

oldstring[startposition:endpo

sition]

Tehát, a lenti kóddal kiszed-hetjük a nekünk kel lő részeket.

Ezután meg kel l szereznünkazt az azonosítót, ami a name

# Get text of cache name up to the phrase "Open Cache: "

CacheName = w1.text[:w1.text.find("Open Cache: ")­1]

# Get the text between "Open Cache: " and "Cache Type: "

OpenCache = w1.text[w1.text.find("Open Cache:

")+12:w1.text.find("Cache Type: ")­1]

# More of the same

CacheType = w1.text[w1.text.find("Cache Type:

")+12:w1.text.find("Cache Size: ")­1]

CacheSize = w1.text[w1.text.find("Cache Size:

")+12:w1.text.find("Difficulty: ")­1]

Difficulty= w1.text[w1.text.find("Difficulty:

")+12:w1.text.find("Terrain : ")­1]

Terrain = w1.text[w1.text.find("Terrain : ")+12:]

Page 11: IssuePY02 Hu

full circle magazin Python 2. kötet tartalom ^1 1

Programozzunk Pythonban ‐ 10. résztag tulajdonságában van.Attribútumok jelenlétét ígykérdezzük le (természetesenmost tudjuk, hogy mik vannak):

if w1.keys():

for name,value in

w1.items():

if name == 'id':

CacheID = value

Foglalkozzunk most amaradék - koordináták, típus ésl ink - elemekkel , a kóditt középen látható:

Végül kiíratjuk alentebb látható módon.

Már most eleget tu-dunk ahhoz, hogy alegtöbb XML fáj lt olvas-hassuk. Mint máskor is,a tel jes forráskódot ahonlapomról lehetletölteni .

Következő alkalom-mal felhasznál juk meg-szerzett XML tudásun-kat egy csodálatos idő-járásjelentő oldal lekér-dezéséhez és terminál-ban való megjelenítésé-hez.

Jó szórakozást!

elif w1.tag == "coord":

if w1.keys():

for name,value in w1.items():

if name == "lat":

Lat = value

elif name == "lon":

Lon = value

elif w1.tag == "type":

GType = w1.text

elif w1.tag == "link":

if w1.keys():

for name, value in w1.items():

Info = value

Link = w1.text

print "Cache Name: ",CacheName

print "Cache ID: ",CacheID

print "Open Cache: ",OpenCache

print "Cache Type: ",CacheType

print "Cache Size: ",CacheSize

print "Difficulty: ", Difficulty

print "Terrain: ",Terrain

print "Lat: ",Lat

print "Lon: ",Lon

print "GType: ",GType

print "Link: ",Link

import elementtree. ElementTree as ETtree = ET. parse( ' Cache. loc' )w = tree. find( ' . //waypoint' )for w1 in w:

if w1. tag == "name":# Get text of cache name up to the phrase "Open Cache:

"CacheName = w1. text[ : w1. text. find( "Open Cache: ") -1]# Get the text between "Open Cache: " and "Cache Type:

"OpenCache = w1. text[w1. text. find( "Open Cache:

") +12: w1. text. find( "Cache Type: ") -1]# More of the sameCacheType = w1. text[w1. text. find( "Cache Type:

") +12: w1. text. find( "Cache Size: ") -1]CacheSize = w1. text[w1. text. find( "Cache Size:

") +12: w1. text. find( "Difficulty: ") -1]Difficulty= w1. text[w1. text. find( "Difficulty:

") +12: w1. text. find( "Terrain : ") -1]Terrain = w1. text[w1. text. find( "Terrain : ") +12: ]if w1. keys( ) :

for name, value in w1. items( ) :if name == ' id' :

CacheID = valueelif w1. tag == "coord":

if w1. keys( ) :for name, value in w1. items( ) :

if name == "lat":Lat = value

elif name == "lon":Lon = value

elif w1. tag == "type":GType = w1. text

elif w1. tag == "link":if w1. keys( ) :

for name, value in w1. items( ) :Info = value

Link = w1. textprint "Cache Name: ", CacheNameprint "Cache ID: ", CacheIDprint "Open Cache: ", OpenCacheprint "Cache Type: ", CacheTypeprint "Cache Size: ", CacheSizeprint "Difficulty: ", Difficultyprint "Terrain: ", Terrainprint "Lat: ", Latprint "Lon: ", Lonprint "GType: ", GTypeprint "Link: ", Linkprint "="*25

print "finished"

Greg Walters a RainyDay SolutionsKft. tulajdonosa, amely egy tanács-adó cég Aurorában, Coloradóban,Greg pedig 1 972 óta foglalkozikprogramozással. Szeret főzni, túráz-ni, zenét hallgatni, valamint a csa-ládjával tölteni a szabadidejét.

Page 12: IssuePY02 Hu

full circle magazin Python 2. kötet tartalom ^1 2

HogyanokÍrta: Greg Walters

Programozzunk Pythonban - 1 1 . rész

Legutóbb azt ígértem,hogy az XML tudásunkatfelhasználva időjárási in-formációkat fogunk le-

szedni egy weboldalról és egyterminálban jelenítjük meg azo-kat. Nos, ez most elérkezett.

A www.wunderground.comAPI-ját fogjuk felhasználni . Márhal lom a torkotokból felmoraj lókérdést: „Az meg mit jelent,hogy API?”. Az API az Appl ica-tion Programming Interface(azaz alkalmazás programozói

interfész) rövidítése. Ez egydivatos kifejezés arra, amikoregy másik programhoz kapcso-lódunk. Gondol j az importáltfüggvénykönyvtárakra. Néme-lyikük önál ló alkalmazásként isfuttatható, de függvénykönyv-tárként importálva a legtöbbfunkciót saját programunkbanis felhasználhatjuk, s így hasz-nálatba vehetjük másvalakikódját. Esetünkben időjárásiinformációkat fogunk lekérdez-ni a wunderground weboldalról ,speciál isan formázott URL cí-mek segítségével anélkül , hogyböngészőt használnánk. Egye-sek szerint az API olyan, mintegy másik program titkos hátsóbejárata, amit a programozó(k)direkt nekünk készítettek. Így,vagy úgy, ez az alkalmazásnakegy olyan kiegészítése, amivelannak más alkalmazásokbantörténő felhasználását segítielő.

Érdekesen hangzik? Nos,olvass tovább, kedvesPadawanom.

Izzítsd be a kedvenc böngé-sződet és irány a www.wunder-

ground.com. Most írd be az irá-nyítószámod, vagy egy várostés egy ál lamot (vagy egy orszá-got) a kereső mezőbe. Itt ren-geteg információt talá lsz. Mostugorjunk az API weboldalára:http: //wiki .wunderground.com/index.php/API_-_XML

Az egyik első dolog, amitészreveszel , az API felhaszná-lási feltételei . Kérlek, olvasd el ,és tartsd be. Nem fárasztóak ésigazán könnyen betarthatók.Számunkra a GeoLookupXML,WXCurrentObXML, AlertsXML ésForecastXML hívások lesznekérdekesek. Szánj egy kis időt azátolvasásukra.

A GeoLookupXML rutin tanul-mányozását rád bízom. Két má-sik parancsra öszpontosítunk,most a WXCurrentObXML-re(aktuál is ál lapot) és legköze-lebb a ForecastXML-re (előre-jelzés).

I tt a l ink a WXCurrentObXML-hez:http: //api .wunderground.com/auto/wui/geo/WXCurrentObXML/index.xml?query=80013

Az Amerikai Egyesült Ál la-mokban a 80013-as irányító-számot írd át a sajátodra, vagyha más országban élsz, meg-próbálhatsz várost és országotmegadni így: Paris, France,vagy London, England.

I tt a ForecastXML-hez tarto-zó l ink:http: //api .wunderground.com/auto/wui/geo/ForecastXML/index.xml?query=80013

Itt is írd át a 80013-as irá-nyítószámot a sajátodra, vagyadj meg egy várost és egy or-szágot.

Kezdjük az aktuál is informá-ciókkal . Másold a címet a ked-venc böngésződbe. Temérdekinformációt kapsz cserébe. El-döntheted, melyikeket tartodigazán fontosnak, de mi csakpár elemet fogunk megvizs-gálni .

Példánkban a következőcímkékre fordítunk figyelmet:

display_location

Előző részek:FCM 27. -36. számokbanaz 1. -10. részek

Itt használható:

Kategóriák:

Eszközök:

GrafikaFej lesztés Internet M/média Rendszer

MerevlemezCD/DVD USB eszköz Laptop Vezetéknélkül i

Page 13: IssuePY02 Hu

full circle magazin Python 2. kötet tartalom ^1 3

Programozzunk Pythonban ‐ 11. részobservation_time

weather

temperature_string

relative_humidity

wind_string

pressure_string

Ezt a l istát természetesenbővítheted, ha más címkékre iskíváncsi vagy. Példánk azonbanezekkel a címkékkel is elegendőtámpontot nyújt majd tetszőle-ges irányú és mértékű folyta-táshoz.

Most, hogy tudjuk, mit fo-gunk keresni , kezdjük el lekó-dolni az alkalmazásunkat.Nézzük a programot nagyvonalakban.

Először megvizsgál juk, mitkért tőlünk a felhasználó. Hamegadott egy címet, akkor az-zal , egyébként pedig a főprog-ramban rögzített, a lapértelme-zett címmel dolgozunk. Eztátadjuk a getCurrents rutinnak.A címet beépítjük a webes le-kérdezésbe. A válasz fogadásá-ra és objektummá alakításáraaz url l ib.urlopen-t használ juk,majd a létrejött objektumot át-adjuk az ElementTree függ-vénykönyvtár parse függvé-nyének. Ezután lezárjuk a we-

bes kapcsolatot és elkezdjükmegkeresni a címkéinket. Talá-lat esetén a címke szövegét el-mentjük egy változóba, amibőlkésőbb majd kiírhatjuk a kime-netre. Amint megvan mindenadatunk, megjelenítjük őket.Elég egyszerű koncepció.

Kezdjük azzal , hogy a fáj-lunknak a w_currents.py nevetadjuk. I tt a kódunk importrésze:

from xml.etree import

ElementTree as ET

import urllib

import sys

import getopt

Aztán írjunk egy pár sorsúgószöveget (jobbra fent) azimportok fölé.

Mindenképpen tripla idéző-jeleket használ j . Így lehet több-soros kommenteket készíteni .Ezt a részt később még egykicsit részletezzük.

Most hozzuk létre az osztá-lyok vázát (jobbra lent) és akövetkező oldalon látható főrutinokat.

""" w_currents.py

Returns current conditions, forecast and alerts for a

given zipcode from WeatherUnderground.com.

Usage: python wonderground.py [options]

Options:

­h, ­­help Show this help

­l, ­­location City,State to use

­z, ­­zip Zipcode to use as location

Examples:

w_currents.py ­h (shows this help information)

w_currents.py ­z 80013 (uses the zip code 80013 as

location)

"""

class CurrentInfo:

"""

This routine retrieves the current condition xml data

from WeatherUnderground.com

based off of the zip code or Airport Code...

currently tested only with Zip Code and Airport code

For location,

if zip code use something like 80013 (no quotes)

if airport use something like "KDEN" (use double­quotes)

if city/state (US) use something like "Aurora,%20CO" or

“Aurora,CO” (use double­quotes)

if city/country, use something like "London,%20England"

(use double­quotes)

"""

def getCurrents(self,debuglevel,Location):

pass

def output(self):

pass

def DoIt(self,Location):

pass

#=========================================

# END OF CLASS CurrentInfo()

#=========================================

Page 14: IssuePY02 Hu

full circle magazin Python 2. kötet tartalom ^1 4

Programozzunk Pythonban ‐ 11. részKorábbi cikkekből biztosan

emlékszel az „if __name__” sor-ra. Ha önál ló alkalmazáskénthívjuk meg ezt a sort, akkor amain rutin fog lefutni - el lenke-ző esetben programunkat egyfüggvénykönyvtár részekénthasznál juk fel . A main rutinbakerülve megvizsgál juk a kapottparamétereket, ha egyáltalánvan i lyen.

Ha a felhasználó a „-h”, vagy„--help” paramétert adta meg,akkor a programkód elején lévőtripla-idézőjeles súgósorokatírjuk ki . Ezt a usage rutin hajtjavégre a __doc__ kiíratásával .

Ha a felhasználó a „-l” (cím),vagy a „-z” (irányítószám) kap-csolót adja meg, azzal felül írjaa beépített címet. Ha címetadsz meg, mindenképpen teddidézőjelek közé és soha nehasznál j szóközöket. Például , aTexas-i Dal lasra vonatkozó ak-tuál is értékeket megkaphatod a-l "Dal las,Texas" paramétere-zéssel .

Szemfüles olvasóink bizto-san észrevették, hogy a -z és -lkapcsolók nagyjából azonosak.Az -l működését átalakíthatod

úgy, hogy megkeresve a szókö-zöket, újraformázza a karakter-láncot, mielőtt átadja a rutin-nak. Ezt akár most meg is tehe-ted.

Végül létrehozunk egy pél-dányt a CurrentInfo osztályunk-ból , amit currents-nek neve-zünk el , és a címet átadjuk a„DoIt” rutinnak. Töltsük is kinyomban:

def DoIt(self,Location):

self.getCurrents(1,Location)

self.output()

Nagyon egyszerű. A címet ésa debug levelt átadjuk agetCurrents rutinnak, majdmeghívjuk az output rutint. Bárkiírathatnánk az eredménytegyszerűen közvetlenül agetCurrents-ből is, rugalmasab-bá tesszük a programunkat az-által , ha szükség esetén más-más módon is kiírathatjuk azeredményt.

A getCurrents forrása akövetkező oldalon található.

Van itt egy debuglevel nevűparaméterünk. Ennek segítsé-

gével hasznos információkatírathatunk ki , ha a dolgok nempont úgy alakulnának, ahogyszerettük volna. Ez a programo-zás korai szakaszában is hasz-nos lehet. Ha a programod mű-ködése már tel jes megelége-déssel tölt el , minden debug-level lel kapcsolatos részt töröl-hetsz. Mielőtt közzéteszed aprogramot a nagyérdemű szá-

mára, mint minden hasonlóesetben, ezt a kódot feltétlenültávolítsd el , majd mégegyszerteszteld le, mielőtt útjára indí-tod.

Most egy try/exceptwrapperrel fogjuk biztosítani aprogramunkat lefagyás el len,ha valami rosszul sülne el . A tryoldalon beál l ítjuk az URL-t és

def usage():

print __doc__

def main(argv):

location = 80013

try:

opts, args = getopt.getopt(argv, "hz:l:", ["help=",

"zip=", "location="])

except getopt.GetoptError:

usage()

sys.exit(2)

for opt, arg in opts:

if opt in ("­h", "­­help"):

usage()

sys.exit()

elif opt in ("­l", "­­location"):

location = arg

elif opt in ("­z", "­­zip"):

location = arg

print "Location = %s" % location

currents = CurrentInfo()

currents.DoIt(location)

#============================================

# Main loop

#============================================

if __name__ == "__main__":

main(sys.argv[1:])

Page 15: IssuePY02 Hu

full circle magazin Python 2. kötet tartalom ^1 5

Programozzunk Pythonban ‐ 11. részegy 8 másodperces határidőt(url l ib.socket.setdefaulttimeout(8)) . Ezt azért tesszük, mert awunderground néha túlterheltés nem válaszol . Így nem fo-gunk ülni és várni a webre avégtelenségig. Ha többet sze-retnél megtudni az url l ibről , jóki indulópont ahttp: //docs.python.org/l ibrary/url l ib.html .

Ha bármi váratlan történik,átkerülünk az except részbe,kiírunk egy hibaüzenetet, éski lépünk (sys.exit(2)) .

Feltételezve, hogy mindenműködik, neki látunk a címkékkeresésének. Elsőként a címün-ket keressük ezzel az utasítás-sal : tree.findal l ("//ful l " ) . Emlé-kezzünk csak, a tree az ele-menttree elemzéséből szárma-zó objektum. Hogy pontosan

mit ad vissza a website API , aztaz alábbiakban láthatjuk.

Ez a <ful l> címke első elő-fordulása, ami esetünkben az„Aurora, CO” értéket visel i . Eztakarjuk címünkként felhasznál-ni . Ezután az „observation_time” címkét keressük, azaz aztaz időpontot, amikor az aktuál isinformációk rögzítve lettek.Ugyanezzel a módszerrel keres-sük meg az összes szükségesinformációt.

Végül meghívjuk az outputrutinunkat, ami a következőoldal bal felső részén található.

I tt egyszerűen kiírjuk aváltozókat.

Ennyi az egész. Egy példakimenet az én irányítószá-mommal és 1-es debuglevel

def getCurrents(self,debuglevel,Location):

if debuglevel > 0:

print "Location = %s" % Location

try:

CurrentConditions =

'http://api.wunderground.com/auto/wui/geo/WXCurrentObXML

/index.xml?query=%s' % Location

urllib.socket.setdefaulttimeout(8)

usock = urllib.urlopen(CurrentConditions)

tree = ET.parse(usock)

usock.close()

except:

print 'ERROR ­ Current Conditions ­ Could not get

information from server...'

if debuglevel > 0:

print Location

sys.exit(2)

# Get Display Location

for loc in tree.findall("//full"):

self.location = loc.text

# Get Observation time

for tim in tree.findall("//observation_time"):

self.obtime = tim.text

# Get Current conditions

for weather in tree.findall("//weather"):

self.we = weather.text

# Get Temp

for TempF in tree.findall("//temperature_string"):

self.tmpB = TempF.text

#Get Humidity

for hum in tree.findall("//relative_humidity"):

self.relhum = hum.text

# Get Wind info

for windstring in tree.findall("//wind_string"):

self.winds = windstring.text

# Get Barometric Pressure

for pressure in tree.findall("//pressure_string"):

self.baroB = pressure.text

getCurrents rutin

<display_location>

<full>Aurora, CO</full>

<city>Aurora</city>

<state>CO</state>

<state_name>Colorado</state_name>

<country>US</country>

<country_iso3166>US</country_iso3166>

<zip>80013</zip>

<latitude>39.65906525</latitude>

<longitude>­104.78105927</longitude>

<elevation>1706.00000000 ft</elevation>

</display_location>

Page 16: IssuePY02 Hu

full circle magazin Python 2. kötet tartalom ^1 6

Programozzunk Pythonban ‐ 11. rész

értékkel az oldal al ján látható.

Vedd figyelembe, kérlek, hogyolyan tageket választottam, ame-lyek a Farenheit és Celsius érté-keket is tartalmazzák. Ha pél-dául csak a Celsius értékeketszeretnéd megjeleníteni , a<temperature_string> címkehelyett a <temp_c> címkét ishasználhatod.

A tel jes forrás letölthető a:http: //pastebin.com/4ibJGm74címről .

Legközelebb az API „előre-jelzés” részére koncentrálunk.Addig is, jó szórakozást!

def output(self):

print 'Weather Information From Wunderground.com'

print 'Weather info for %s ' % self.location

print self.obtime

print 'Current Weather ­ %s' % self.we

print 'Current Temp ­ %s' % self.tmpB

print 'Barometric Pressure ­ %s' % self.baroB

print 'Relative Humidity ­ %s' % self.relhum

print 'Winds %s' % self.winds

Location = 80013

Weather Information From Wunderground.com

Weather info for Aurora, Colorado

Last Updated on May 3, 11:55 AM MDT

Current Weather ­ Partly Cloudy

Current Temp ­ 57 F (14 C)

Barometric Pressure ­ 29.92 in (1013 mb)

Relative Humidity ­ 25%

Winds From the WNW at 10 MPH

Script terminated.

Greg Walters a RainyDay SolutionsKft. tulajdonosa, amely egy tanács-adó cég Aurorában, Coloradóban,Greg pedig 1 972 óta foglalkozikprogramozással. Szeret főzni, túráz-ni, zenét hallgatni, valamint a csa-ládjával tölteni a szabadidejét.

Page 17: IssuePY02 Hu

full circle magazin Python 2. kötet tartalom ^1 !

HogyanokÍrta: Greg Walters

Programozzunk Pythonban - 1 2. rész

Előző alkalommal meg-néztük a wundergroundAPI-ját és írtunk is egykis kódot az aktuál is

időjárás lekérdezéséhez. Mostaz API időjárás előrejelző részé-vel fogunk foglalkozni . Ha nemvolt alkalmunk elolvasni az elő-ző két, XML-lel foglalkozó cikket- különösképpen az előzőt - ak-kor, mielőtt továbblépnénk min-denképpen fussuk át őket.

Mint ahogy az aktuál is időjá-rásnak is volt egy webcíme, úgy

az előrejelzésnek is van. Azelőrejelzés XML oldala:http: //api .wunderground.com/auto/wui/geo/ForecastXML/index.xml?query=80013

Akárcsak múltkor, most is a„80013”-at meg tudjuk változ-tatni a mi Város/Országunkra,Város/Ál lamunkra vagy irányító-számunkra. Valószínűleg 600sornyi XML kódot fogunk vissza-kapni . A gyökérelem a „fore-cast” (előrejelzés), melyneknégy gyermekeleme van:„termsofservice” (a szolgálta-tás feltételei ) , „txt_forecast”(szöveges előrejelzés), „simp-leforecast” (egyszerű előrejel-zés) és „moon_phase” (holdfá-zis) . Mi csak a „txt_forecast”-raés a „simpleforecast”-ra fogunkszorítkozni .

Mivel már átnéztük a usage,main és „if __name__” részeket,ezért ezeket rátok hagyom, ésmost csak az igazán érdekesrészekre fogunk koncentrálni .Már mutattam egy darabkát atxt_forecast-ból , ezért kezdjünkazzal .

Lent látható a környékemtxt_forecastjának egy kis szele-te.

A txt_forecast szülőelem u-tán találunk egy „date” (dá-tum), és egy „number” (szám)elemet, majd egy olyan fore-castday nevű tagot aminekvannak saját gyermekei , ezek:period (ciklus), icon (ikon),icons (ikonok), title (cím) ésvalami fcttext nevű dolog, az-tán ezek ismétlődnek. Az elsődolog amit észrevehetünk, azaz, hogy a txt_forecast alatt a

dátum valójában egy időpont.Ez gyakorlati lag az előrejelzéskiadásának ideje. A <number>tag mondja meg, hogy mennyielőrejelzés van az elkövetkező24 órára. Nem emlékszemolyan esetre, amikor ez az ér-ték kettőnél kevesebb lett vol-na. Minden 24 órás periódushoz(<forecastday>) tartozik egyciklus szám, többféle ikon beál-l ítás, egy cím opció („Today”[ma], „Tonight” [ma este], „To-morrow” [holnap]), és a „simpleforecast” (rövid előrejelzés)szövege. Ez egy gyors összeg-

<txt_forecast>

<date>3:31 PM MDT</date>

<number>2</number>

−<forecastday>

<period>1</period>

<icon>nt_cloudy</icon>

+<icons></icons>

<title>Tonight</title>

−<fcttext>

Mostly cloudy with a 20

percent chance of thunderstorms in the evening...then

partly cloudy after midnight. Lows in the mid 40s.

Southeast winds 10 to 15 mph shifting to the south after

midnight.

</fcttext>

</forecastday>

+<forecastday></forecastday>

</txt_forecast>

Előző részek:FCM 27. -37. számokbanaz 1. -11. részek

Itt használható:

Kategóriák:

Eszközök:

GrafikaFej lesztés Internet M/média Rendszer

MerevlemezCD/DVD USB eszköz Laptop Vezetéknélkül i

Page 18: IssuePY02 Hu

full circle magazin Python 2. kötet tartalom ^1 !

Programozzunk Pythonban ‐ 12. részzése a következő 12 óra időjá-rásának.

Mielőtt neki látnánk kódolni ,nem ártana egy pi l lantást vetniaz xml <simpleforecast> részé-re, mely jobbra látható.

Van egy <forecastday>tagünk minden egyes időjárásiciklushoz, mely általában hatnapot jelent, beleértve a maitis. Az alábbi adatok ál lnak ren-delkezésünkre: dátum többféleformátumban (én a <pretty>elemet szeretem), az előrejel-zett hőmérsékletek Fahren-heitben és Celsiusban, átlagoskörülmények, különböző iko-nok, egy égbolt ikon (az elem-zőál lomás égboltjának ál lapo-ta), és a „pop”, ami a „Proba-bi l i ty Of Percipitation” (csapa-dékvalószínűség). Néhányérdekes információt szolgáltat a<moon_phase> tag, mint pél-dául a naplemente, napfelkelteés hold információkat.

Most nézzük a kódot. I tt vanaz import szakasz:

from xml.etree import

ElementTree as ET

import urllib

import sys

import getopt

Most kezdődhet a mai elő-adás. Létrehozunk egy __init__szubrutint a számunkra szüksé-ges változók beál l ításához éskitörléséhez. Ezt jobbra fenn akövetkező oldalon láthatjuk.

Ha nem érdekel minketmindkét hőmérséklet használa-ta (Fahrenheit és Celsius) , akkorhagyjuk ki a megfelelő változó-csoportot. Én mindkettőt alkal-mazni fogom.

Ezután elkészítjük a lekérde-zés metódusát, mely letölti azelőrejelzést. Ez látható a követ-kező oldalon lent.

Mindez nagyon hasonló amúltkori , jelenlegi ál lapotokatlekérdező rutinhoz. Az egyetlennagy különbség (eddig) a hasz-nált URL-ben van. Ezen a pon-ton azonban néhány dologmegváltozik. Mivel több olyangyermek is van, melynek a szü-lőn belül ugyanaz a neve, ezérta parseoló hívásokat egy kissémáshogy kel l használni . A kód akövetkező oldalon, balra fennlátható.

<simpleforecast>

−<forecastday>

<period>1</period>

−<date>

<epoch>1275706825</epoch>

<pretty_short>9:00 PM MDT</pretty_short>

<pretty>9:00 PM MDT on June 04, 2010</pretty>

<day>4</day>

<month>6</month>

<year>2010</year>

<yday>154</yday>

<hour>21</hour>

<min>00</min>

<sec>25</sec>

<isdst>1</isdst>

<monthname>June</monthname>

<weekday_short/>

<weekday>Friday</weekday>

<ampm>PM</ampm>

<tz_short>MDT</tz_short>

<tz_long>America/Denver</tz_long>

</date>

−<high>

<fahrenheit>92</fahrenheit>

<celsius>33</celsius>

</high>

−<low>

<fahrenheit>58</fahrenheit>

<celsius>14</celsius>

</low>

<conditions>Partly Cloudy</conditions>

<icon>partlycloudy</icon>

+<icons>

<skyicon>partlycloudy</skyicon>

<pop>10</pop>

</forecastday>

...

</simpleforecast>

Page 19: IssuePY02 Hu

full circle magazin Python 2. kötet tartalom ^1 9

Programozzunk Pythonban ‐ 12. részclass ForecastInfo:

def __init__(self):

self.forecastText = [] # Today/tonight forecast

information

self.Title = [] # Today/tonight

self.date = ''

self.icon = [] # Icon to use for conditions

today/tonight

self.periods = 0

self.period = 0

#==============================================

# Extended forecast information

#==============================================

self.extIcon = [] # Icon to use for extended

forecast

self.extDay = [] # Day text for this forecast

("Monday", "Tuesday" etc)

self.extHigh = [] # High Temp. (F)

self.extHighC = [] # High Temp. (C)

self.extLow = [] # Low Temp. (F)

self.extLowC = [] # Low Temp. (C)

self.extConditions = [] # Conditions text

self.extPeriod = [] # Numerical Period information

(counter)

self.extpop = [] # Percent chance Of

Precipitation

def GetForecastData(self,location):

try:

forecastdata = 'http://api.wunderground.com/auto/wui/geo/ForecastXML/index.xml?query=%s' % location

urllib.socket.setdefaulttimeout(8)

usock = urllib.urlopen(forecastdata)

tree = ET.parse(usock)

usock.close()

except:

print 'ERROR ­ Forecast ­ Could not get information from server...'

sys.exit(2)

#=================================

# Get the forecast for today and (if available)

tonight

#=================================

fcst = tree.find('.//txt_forecast')

for f in fcst:

if f.tag == 'number':

self.periods = f.text

elif f.tag == 'date':

self.date = f.text

for subelement in f:

if subelement.tag == 'period':

self.period=int(subelement.text)

if subelement.tag == 'fcttext':

self.forecastText.append(subelement.text)

elif subelement.tag == 'icon':

self.icon.append( subelement.text)

elif subelement.tag == 'title':

self.Title.append(subelement.text)

Page 20: IssuePY02 Hu

full circle magazin Python 2. kötet tartalom ^20

Programozzunk Pythonban ‐ 12. részVegyük észre, hogy egy

tree.find hívást és egy for cik-lust használunk az adatok bejá-rásához. Szomorú dolog, hogya Pythonban - más nyelvekkelel lentétben - SELECT/CASE ve-zérlési szerkezet nincs. AzIF/ELIF megoldás azonban elégjól működik, csak egy kicsitormótlanabb. Nézzük meg akódot közelebbről . Az fcstváltozóhoz hozzárendel jük a<txt_forecast> elemben lévőösszes adatot. Ezzel megleszminden információ az adottcsoportból . Ezután megkeres-sük a <date> és <number>tagokat - mivel ők egyszerű„első szintű” elemek - és be-töltjük őket a változóinkba.Ekkor a dolgok egy kicsit to-vább bonyolódnak. Vessünkismét egy pi l lantást a kapottxml példánkra. A <forecast-day> elemnek két példányavan. A <forecastday> alatt lévőalelemek a <period>, <icon>,<icons>, <title> és <fcttext>.Egy ciklussal átiterálunk rajtuk,miközben ismét az IF utasításthasznál juk a változókba valóbetöltésükhöz.

Ezt követően meg kel l néz-nük az elkövetkező X nap rész-letesebb előrejelzését. Gyakor-

lati lag ugyanazt a módszerthasznál juk. Ezt jobbra láthatjuk.

Létre kel l hoznunk az output(kimenet) rutint. Ez - akárcsakmúltkor - most is elég általánoslesz. A kódot a következő olda-lon talál juk.

Ismét, ha nem akarjuk mind-két hőmérséklet - a Celsiust ésFahrenheitet- is használni , ak-kor módosítsuk a kódot megfe-lelően. Végül van egy „Dolt”szubrutinunk:

def

DoIt(self,Location,US,Include

Today,Output):

self.GetForecastData(Lo

cation)

self.output(US,IncludeT

oday,Output)

Most a következőképpen hív-hatjuk a rutint:

forecast = ForecastInfo()

forecast.DoIt('80013',1,0,0)

# Insert your own postal code

Ennyi lenne mostanra. Azalert részt meghagyom nektek,ha esetleg végig akarnátokmenni rajta.

A tel jes működő kód itttalá lható:http: //pastebin.com/wsSXMXQx

Jó szórakozást a következőalkalomig.

#=================================

# Now get the extended forecast

#=================================

fcst = tree.find('.//simpleforecast')

for f in fcst:

for subelement in f:

if subelement.tag == 'period':

self.extPeriod.append(subelement.text)

elif subelement.tag == 'conditions':

self.extConditions.append(subelement.text)

elif subelement.tag == 'icon':

self.extIcon.append(subelement.text)

elif subelement.tag == 'pop':

self.extpop.append(subelement.text)

elif subelement.tag == 'date':

for child in subelement.getchildren():

if child.tag == 'weekday':

self.extDay.append(child.text)

elif subelement.tag == 'high':

for child in subelement.getchildren():

if child.tag == 'fahrenheit':

self.extHigh.append(child.text)

if child.tag == 'celsius':

self.extHighC.append(child.text)

elif subelement.tag == 'low':

for child in subelement.getchildren():

if child.tag == 'fahrenheit':

self.extLow.append(child.text)

if child.tag == 'celsius':

self.extLowC.append(child.text)

Greg Walters a RainyDay SolutionsKft. tulajdonosa, amely egy tanács-adó cég Aurorában, Coloradóban,Greg pedig 1 972 óta foglalkozikprogramozással. Szeret főzni, túráz-ni, zenét hallgatni, valamint a csa-ládjával tölteni a szabadidejét.

Page 21: IssuePY02 Hu

full circle magazin Python 2. kötet tartalom ^21

Programozzunk Pythonban ‐ 12. rész

def output(self,US,IncludeToday,Output):

# US takes 0,1 or 2

# 0 = Centigrade

# 1 = Fahrenheit

# 2 = both (if available)

# Now print it all

if Output == 0:

for c in range(int(self.period)):

if c <> 1:

print '­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­'

print 'Forecast for %s' %

self.Title[c].lower()

print 'Forecast = %s' %

self.forecastText[c]

print 'ICON=%s' % self.icon[c]

print '­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­'

print 'Extended Forecast...'

if IncludeToday == 1:

startRange = 0

else:

startRange = 1

for c in range(startRange,6):

print self.extDay[c]

if US == 0: #Centigrade information

print '\tHigh ­ %s(C)' %

self.extHigh[c]

print '\tLow ­ %s(C)' % self.extLow[c]

elif US == 1: #Fahrenheit information

print '\tHigh ­ %s(F)' %

self.extHigh[c]

print '\tLow ­ %s(F)' % self.extLow[c]

else: #US == 2 both(if available)

print '\tHigh ­ %s' % self.extHigh[c]

print '\tLow ­ %s' % self.extLow[c]

if int(self.extpop[c]) == 0:

print '\tConditions ­ %s.' %

self.extConditions[c]

else:

print '\tConditions ­ %s. %d%% chance

of precipitation.' %

(self.extConditions[c],int(self.extpop[c]))

Page 22: IssuePY02 Hu

full circle magazin Python 2. kötet tartalom ^22

HogyanokÍrta: Greg Walters

Programozzunk Pythonban - 1 3. rész

Ebben a hónapban aCurses Pythonban valóhasználatáról fogunkbeszélgetni . Nem, nem

arról lesz szó, hogy hogyan ká-romkodjunk Pythonul (curseing= káromkodás, ford. ) , de akárerre is vetemedhetünk, haszükségét éreznénk. Most azon-ban a Curses modul használa-tát nézzük meg, mel lyel cifráb-bá tehetjük a képernyőkimene-tet.

Ha elég idősek vagyünk, ak-kor emlékezhetünk a számító-gépek korai időszakára, amikormég üzleti nagygépeink voltak,és buta kis terminálokkal (ké-pernyő és bi l lentyűzet) lehetetbe-, i l letve kiírni adatokat. Többterminál is csatlakozhatott egyszámítógéphez. A gond csak azvolt, hogy a számítógép-termi-nálok nem voltak túl okosak.Nem áltak rendelkezésünkre seablakok, se színek, se semmi,csak 24 darab, 80 karakternyihosszú sor (legjobb esetben).Még a DOS és a CP/M idősza-kában - amikor a személyi szá-mítógépek elterjedtek - is csak

ennyink volt. Amikor a progra-mozó bonyolultabb kiíratásondolgozott (legalábbis ahhoz azidőszakhoz képest) - kiváltkép-pen adat ki- és beíráskor -négyzetrácsos papírt használ-tak a képernyő megtervezésé-hez. Minden egyes négyzet egykarakterpozíciónak felelt meg.Amikor terminálban futó Pythonprogrammal dolgozunk, mégmindig a 24x80-as ki jelzővelkel l megküzdenünk. Habár, ezaz akadály könnyen legyőzhetőnémi előrelátással és előkészü-lettel . Tehát, csak el kel l men-nünk venni egy-két füzetet ahelyi papír-írószer boltból .

Mindenesetre vágjunk beleelső Curses programunkba, amijobbra fenn látható. Miután ve-tettünk egy pi l lantást a kódra,elmagyarázom az egészet.

Rövid és egyszerű. Ki is ele-mezzük soronként. Az elsőbenletudjuk az importja inkat, amik-nek már elég ismerőseknek kel-lene lenniük mostanra. Ezutánlétrehozzuk az új Curses képer-nyő objektumot, inicia l izál juk,

majd meghívjuk a myscreen ob-jektumot (myscreen = curses. i -nitscr()) . Ez olyan mint egy vá-szon, amire majd festeni fo-gunk. Ezt követően használ juka myscreen.border(0) hívástegy szegély megrajzolásáshoza képernyő körül . Mindez nemkötelező, de jobban fog tőle ki-nézni a ki jelző. Aztán a Cursesaddstr() metódusát használ jukegy szöveg „kiírásához” a 12-iksor 25-ik pozíciójától . Végülmeghívjuk a refresh() tagfügg-vényt, ami láthatóvá teszi mun-kánkat. Ha nem frissítenénk aképernyőt, akkor a változtatá-sok nem lennének érzékelhe-tők. Ezután megvárjuk, amíg afelhasználó megnyom egy gom-

bot (getch), majd felszabadít-juk a ki jelző objektumot(endwin), hogy a terminál aszokásos módon tudjon működ-ni . A curses.endwin() hívás egyKIEMELTEN fontos dolog, mivela konzolunk nagyon ramatyál lapotban lesz, ha nincs meg-hívva. Magyarul , sose felel j tsükel ezt a metódust meghívni mi-előtt befejeznénk az alkalma-zásunk futtatását.

Mentsük el a programotCursesExample1.py néven ésfuttassuk egy terminálban. Né-hány dolgot érdemes megje-gyezni . Mindig, amikor szegé-lyeket használunk, a kerettelelvesztünk egy „használható”

#!/usr/bin/env python

# CursesExample1

#­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­

# Curses Programming Sample 1

#­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­

import curses

myscreen = curses.initscr()

myscreen.border(0)

myscreen.addstr(12, 25, "See Curses, See Curses Run!")

myscreen.refresh()

myscreen.getch()

curses.endwin()

Page 23: IssuePY02 Hu

full circle magazin Python 2. kötet tartalom ^23

Programozzunk Pythonban ‐ 13. részkarakterpozíciót. Továbbá, minda sor, mind a karakter pozíciószáma NULLÁVAL kezdődik. Ezazt jelenti , hogy az első sor a0. -ik, az utolsó a 23. -ik. Azaz, afelső bal sarok pozíciója 0;0 ésaz alsó jobbé 23;79. Nézzünkmeg egy rövid példát (jobbrafenn), mely ezt mutatja be.

A try/final ly blokkok kivételé-vel elég egyszerű dolgok van-nak itt. Emlékezzünk, hogy acurses.endwin NAGYON fontosés mindig meg kel l hívni ki lépéselőtt. Ezzel a módszerrel azon-ban, még ha minden rosszulmegy is, az endwin rutin megfog hívódni . Ugyanez sok másmódon megoldható, de szá-momra ez a legkézenfekvőbb.

Most készítsünk egy jól kiné-ző menürendszert. Ha vissza-

gondolunk néhány számmalkorábra (8. rész), akkor emlé-kezhetünk a szakácskönyvesalkalmazásra, melynek voltegy menüje. Amikor kiírattunkvalamit, akkor minden egy-szerűen fentebb csúszott.Most ezt az ötletet felhasznál-va létrehozunk egy „látszat-menüt”, amit később akár felis használhatunk a szakács-könyves alkalmazás kicsinosí-tásához. Lent látható a régimegoldás.

Ez alkalommal a Cursestfogjuk használni . Kezdjük azalábbi sablonnal . Lehet, hogyhasznos lenne elmenteni ezta kóddarabkát (jobbra lenn)az esetleges jövőbel i prog-ramjainkhoz.

Ahhoz, hogy a fáj lon

#!/usr/bin/env python

# CursesExample2

import curses

#==========================================================

# MAIN LOOP

#==========================================================

try:

myscreen = curses.initscr()

myscreen.clear()

myscreen.addstr(0,0,"0 1 2 3

4 5 6 7")

myscreen.addstr(1,0,"1234567890123456789012345678901234

5678901234567890123456789012345678901234567890")

myscreen.addstr(10,0,"10")

myscreen.addstr(20,0,"20")

myscreen.addstr(23,0, "23 ­ Press Any Key to Continue")

myscreen.refresh()

myscreen.getch()

finally:

curses.endwin()

===================================================

RECIPE DATABASE

===================================================

1 ­ Show All Recipes

2 ­ Search for a recipe

3 ­ Show a Recipe

4 ­ Delete a recipe

5 ­ Add a recipe

6 ­ Print a recipe

0 ­ Exit

===================================================

Enter a selection ­>

#!/usr/bin/env python

#­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­

# Curses Programming Template

#­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­

import curses

def InitScreen(Border):

if Border == 1:

myscreen.border(0)

#==========================================================

# MAIN LOOP

#==========================================================

myscreen = curses.initscr()

InitScreen(1)

try:

myscreen.refresh()

# Your Code Stuff Here...

myscreen.addstr(1,1, "Press Any Key to Continue")

myscreen.getch()

finally:

curses.endwin()

Page 24: IssuePY02 Hu

full circle magazin Python 2. kötet tartalom ^24

Programozzunk Pythonban ‐ 13. részdolgozhassunk a sablon módo-sítása nélkül , előbb mentsük el„cursesmenu1.py” néven.

Mielőtt továbblépnénk a kód-dal , megnézzük az egészet lé-pésekben. Itt ( jobbra fenn) lát-ható a feladatunk pszeudo-kódalakja.

Természetesen ez a pszeu-do-kód csak egy álkód. Ennekel lenére elég jó arra, hogy meg-felelő kép alakul jon ki bennünkaz egész dologról . Mivel mindezcsak egy példa, ezért nem iselemezzük ki jobban, de haszükségét érezzük, akkor elmé-lyülhetünk benne. Kezdjük amain ciklussal (középenjobbra).

Nem sok programozni valóakad itt. Akárcsak a sablonban,itt is megvannak a try| final lyblokkjaink. Inicia l izál juk aCurses ki jelzőt, majd meghívjuka LogicLoop rutint. Ez a kódjobbra lenn látható.

Mivel ez is csak egy példa,ismét nem sok látnivaló akad.Két rutint hívunk meg. Az egyi-ket DoMainMenunek, a másikatMainInKey-nek nevezik. ( Jobbralenn látható) A Do-MainMenu

curses.initscreen

LogicLoop

ShowMainMenu # Show the main menu

MainInKey # This is our main input handling routine

While Key != 0:

If Key == 1:

ShowAllRecipesMenu # Show the All Recipes Menu

Inkey1 # Do the input routines for this

ShowMainMenu # Show the main menu

If Key == 2:

SearchForARecipeMenu # Show the Search for a Recipe Menu

InKey2 # Do the input routines for this option

ShowMainMenu # Show the main menu again

If Key == 3:

ShowARecipeMenu # Show the Show a recipe menu routine

InKey3 # Do the input routine for this routine

ShowMainMenu # Show the main menu again

… # And so on and so on

curses.endwin() # Restore the terminal

# MAIN LOOP

try:

myscreen = curses.initscr()

LogicLoop()

finally:

curses.endwin()

def LogicLoop():

DoMainMenu()

MainInKey()

def DoMainMenu():

myscreen.erase()

myscreen.addstr(1,1,

"========================================")

myscreen.addstr(2,1, " Recipe

Database")

myscreen.addstr(3,1,

"========================================")

myscreen.addstr(4,1, " 1 ­ Show All

Recipes")

myscreen.addstr(5,1, " 2 ­ Search for a

recipe")

myscreen.addstr(6,1, " 3 ­ Show a recipe")

myscreen.addstr(7,1, " 4 ­ Delete a recipe")

myscreen.addstr(8,1, " 5 ­ Add a recipe")

myscreen.addstr(9,1, " 6 ­ Print a recipe")

myscreen.addstr(10,1, " 0 ­ Exit")

myscreen.addstr(11,1,

"========================================")

myscreen.addstr(12,1, " Enter a selection: ")

myscreen.refresh()

Page 25: IssuePY02 Hu

full circle magazin Python 2. kötet tartalom ^25

Programozzunk Pythonban ‐ 13. részmegjeleníti a főmenüt, a Main-InKey pedig lekezel mindenmást.

Figyel jük meg, hogy itt kép-ernyőtörlésen (myscreen.erase)és a kiírandó dolgokon kívülmás nincs. Sehol nem látunkbi l lentyűzetet kezelő kódot. Eza MainInKey feladata, ami ittlenn látható.

Ez is egy igen egyszerű ru-

tin. Mindaddig, amíg a beolva-sott érték nem 0, egy whi le cik-lusban vagyunk. A ciklusban le-el lenőrizzük, hogy a kapott adatmegegyezik-e különböző érté-kekkel , és ha igen, akkor egysor rutint hívunk meg. Végülmikor készen vagyunk, meghív-juk a főmenüt. A legtöbbjüketmostanra már egyedül is megtudjuk oldani , de a 2-es opciót -Search for a Recipe (Receptkeresése) - külön is megnézzük.

def MainInKey():

key = 'X'

while key != ord('0'):

key = myscreen.getch(12,22)

myscreen.addch(12,22,key)

if key == ord('1'):

ShowAllRecipesMenu()

DoMainMenu()

elif key == ord('2'):

SearchForARecipeMenu()

InKey2()

DoMainMenu()

elif key == ord('3'):

ShowARecipeMenu()

DoMainMenu()

elif key == ord('4'):

NotReady("'Delete A Recipe'")

DoMainMenu()

elif key == ord('5'):

NotReady("'Add A Recipe'")

DoMainMenu()

elif key == ord('6'):

NotReady("'Print A Recipe'")

DoMainMenu()

myscreen.refresh()

def SearchForARecipeMenu():myscreen.addstr(4,1, "­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­")myscreen.addstr(5,1, " Search in")myscreen.addstr(6,1, "­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­")myscreen.addstr(7,1, " 1 ­ Recipe Name")myscreen.addstr(8,1, " 2 ­ Recipe Source")myscreen.addstr(9,1, " 3 ­ Ingredients")myscreen.addstr(10,1," 0 ­ Exit")myscreen.addstr(11,1,"Enter Search Type ­> ")myscreen.refresh()

def InKey2():key = 'X'doloop = 1while doloop == 1:

key = myscreen.getch(11,22)myscreen.addch(11,22,key)tmpstr = "Enter text to search in "if key == ord('1'):

sstr = "'Recipe Name' for ­> "tmpstr = tmpstr + sstrretstring = GetSearchLine(13,1,tmpstr)break

elif key == ord('2'):sstr = "'Recipe Source' for ­> "tmpstr = tmpstr + sstrretstring = GetSearchLine(13,1,tmpstr)break

elif key == ord('3'):sstr = "'Ingredients' for ­> "tmpstr = tmpstr + sstrretstring = GetSearchLine(13,1,tmpstr)break

else:retstring = ""break

if retstring != "":myscreen.addstr(15,1,"You entered ­ " + retstring)

else:myscreen.addstr(15,1,"You entered a blank string")

myscreen.refresh()myscreen.addstr(20,1,"Press a key")myscreen.getch()

def GetSearchLine(row,col,strng):myscreen.addstr(row,col,strng)myscreen.refresh()instring = myscreen.getstr(row,len(strng)+1)myscreen.addstr(row,len(strng)+1,instring)myscreen.refresh()return instring

Page 26: IssuePY02 Hu

full circle magazin Python 2. kötet tartalom ^26

Programozzunk Pythonban ‐ 13. részEz a menü rövid és egyszerű.Az InKey2 rutin (előző oldalonjobbra) egy kissé bonyolultabb.

Megint a szokásos whi le cik-lust használ juk. A doloop válto-zót 1-re ál l ítjuk, hogy a ciklusaddig fusson, amíg nincs meg,amit akartunk. A break hívásthasznál juk a ciklusból való ki lé-péshez. A három opció nagyonhasonló. A fő különbség, hogyegy tmpstr nevű változóval kez-dünk, majd hozzáfűzzük azt aszöveget, ami ki lett választva,ezzel egy picit barátságosabbátéve azt. Ezután a keresési szö-veg bekéréséhez a GetSearch-Line-t hívjuk meg. A getstr ru-tinnal karakterek helyett egysztringet olvasunk be a felhasz-nálótól . Végül visszaadjuk a ka-rakterláncot az input rutinunk-nak további feldolgozásra.

A tel jes kód itt érhető el :http: //pastebin.com/ELuZ3T4P

Még egy utolsó dolog. Hamélyebben érdekel a Cursesprogramozás, akkor sok másmódszer is megtalálható a mos-tanin felül . Egy Google keresé-sen kívül a legjobb ki indulóponta hivatalos dokumentáció hon-lapja lehet, mely a

http: //docs.python.org/l ibrary/curses.html címen érhető el .

Találkozunk legközelebb.

HOPSZ!Úgy tűnik, hogy a 11. részkódja a Pastebinen nem voltrendesen indentálva. A he-lyes kód URL-je ez:http: //pastebin.com/Pk74fLF3

Kérlek nézd meg ahttp: //ful lcirclemagazine.pastebin.com lapot az összeseddigi (és jövendő) Pythonkódért.

Greg Walters a RainyDay SolutionsKft. tulajdonosa, amely egy tanács-adó cég Aurorában, Coloradóban,Greg pedig 1 972 óta foglalkozikprogramozással. Szeret főzni, túráz-ni, zenét hallgatni, valamint a csa-ládjával tölteni a szabadidejét.

Page 27: IssuePY02 Hu

full circle magazin Python 2. kötet tartalom ^2!

HogyanokÍrta: Greg Walters

Programozzunk Pythonban - 1 4. rész

Legutóbb a Curses-rőlkezdtünk el beszélni .Most már mélyebbrefogjuk ásni magunkat a

témában, kifejezetten a színek-kel kapcsolatos parancsokrakoncentrálva. Gyorsan össze-foglalom a lényeget, arra azesetre, ha nem olvastátok vol-na az előző cikket. Kezdéskéntbe kel l importálni a curses cso-magot. Ezután meg kel l hívni acurses. initscr metódust. Ahhoz,hogy szöveget írhassunk a kép-ernyőre, a addstr függvényt kel lhasználni , majd a refresh-t aváltoztatások megjelenítésé-hez. Végül , meg kel l hívni acurses.endwin()-t a terminálablak normál is ál lapotra valóvisszaál l ításához.

Most egy rövid és egyszerűprogramot fogunk készíteni ,mely színes lesz. Az egész na-gyon hasonló az eddigiekhez,annyi csak a különbség, hogyvan néhány új parancs. Előszöra curses.start_color() segítségé-vel tudatjuk a rendszerrel , hogymely színekre van szükségünk.Ezt követően beál l ítjuk az előtér

és háttér színpárt. Sok fajtapárt beál l íthatunk, melyeketbármikor fel tudunk használni .Ezt a curses. init_pair függvény-nyel tesszük meg. A szintaxis:

curses.init_pair([pairnumber]

,[foreground

color],[background color])

A „curses.COLOR_” szövegés a szín megfelelő angol nevé-nek az összefűzésével ál l íthat-juk be a színeket. Például :curses.COLOR_BLUE vagycurses.COLOR_GREEN. A vá-lasztási lehetőségeink a követ-kezők: fekete (black), piros(red), green (zöld), sárga(yel low), kék (blue), magenta(bíbor), cyan (ciánkék) és white(fehér). Egyszerűen, nagybe-tűkkel írva fűzzük hozzá a meg-felelőt a “curses.COLOR_”-hozés megkapjuk a színt. Amintbeál l ítottuk a színpárt, felhasz-nálhatjuk a screen.addstr függ-vény utolsó paramétereként:

myscreen.addstr([row],[column

],[text],curses.color_pair(X)

)

I tt láthatjuk az általunk vá-lasztott X színhalmazt.

Mentsük el a kódot (fent lát-ható) colortest1.py néven, majdfuttassuk. Ne próbálkozzunkcurses programok olyan IDE-nbelül i futtatásával , mint az SPEvagy a Dr. Python. A terminálthasznál juk erre.

Egy szürke hátteret kel lenekapnunk három sornyi , külön-

böző színű „This is a test” fel i -rattal . Az elsőnek zöldnek feke-tén, a másodiknak fehéren kék-nek, a harmadiknak bíbornakszürke háttéren kel lene lennie.

Emlékezzünk még a Try/Final ly szerkezetre. Ezzel bizto-síthatjuk be magunkat arra azesetre, hogy ha valami nemmegfelelő történik és a termi-nált vissza kel l á l l ítani normálál lapotba. Van még egy másik

import curses

try:

myscreen = curses.initscr()

curses.start_color()

curses.init_pair(1, curses.COLOR_BLACK,

curses.COLOR_GREEN)

curses.init_pair(2, curses.COLOR_BLUE,

curses.COLOR_WHITE)

curses.init_pair(3,

curses.COLOR_MAGENTA,curses.COLOR_BLACK)

myscreen.clear()

myscreen.addstr(3,1," This is a test

",curses.color_pair(1))

myscreen.addstr(4,1," This is a test

",curses.color_pair(2))

myscreen.addstr(5,1," This is a test

",curses.color_pair(3))

myscreen.refresh()

myscreen.getch()

finally:

curses.endwin()

Page 28: IssuePY02 Hu

full circle magazin Python 2. kötet tartalom ^2!

Programozzunk Pythonban ‐ 14. részmódszer is. A Cursesben talál -ható egy wrapper nevű pa-rancs. A wrapper mindent elvé-gez helyetted. Magától meghív-ja a curses. initscr()-t, a curses.start_color()-t és a curses.end-win()-t. Egyetlen dolgot kel lcsak szem előtt tartani : acurses.wrappert a main függ-vényben kel l meghívni . Ez visz-szaadja neked a screen mutató-ját. Jobbra fenn ugyanaz aprogram látható, csak most acurses.wrapper használatával .

Ezzel a módszerrel nem csakegyszerűbb lesz a program írá-sa, de az endwin meg nem hí-vódása miatt sem kel l aggódni ,ha valami hiba merülne fel .Gyakorlati lag minden munkátelvégez helyettünk.

Most, hogy már egy csomóalapvető dolgot megtanultunk,használ juk is fel ezeket, az el-múlt egy év tapasztalatával ,egy játék létrehozásához. Mie-lőtt belevágnánk, beszél jükmeg, hogy ez mit is takar. A já-ték véletlenszerűen választ egynagybetűt és miközben a kép-ernyő jobb széléről a bal szélé-re mozgatja, egy véletlen pozí-ción le fog esni a képernyő al já-ra. A játékosnak lesz egy „fegy-

vere”, melyet a jobb és bal nyíl -bi l lentyűkkel lehet a lehul ló be-tű alá mozgatni . A szóköz meg-nyomásával lőhetünk. Ha sike-rül lelőni a betűt, mielőtt az el-érné a fegyverünket, akkor ka-punk egy pontot. Ha nem sike-rül , akkor a fegyver felrobban.Ha elvesztünk hármat, akkorvége a játéknak. Egyszerű já-ték, de sok kódot kel l megírnihozzá.

Vágjunk is bele. Végezzük ela kezdeti beál l ításokat, és hoz-zunk létre egy pár rutint. Kezd-jünk egy új projektet, melyetgame1.py-nek fogunk hívni .Először nézzük meg a jobbralent látható kódot.

Ez a kód még nem sokat csi-nál , de ettől függetlenül , egy jóki indulópontot jelent számunk-ra. Figyel jük meg, hogy négydarab init_pair színbeál l ító uta-sításunk van, melyeket a vélet-lenül meghatározott színekhezés a robbanáshoz használunk(ötödik). Most ál l ítsunk be egy-két változót és konstansot. Eze-ket az Game1 osztály __init__rutinjában fogjuk elhelyezni .Cserél jük le a pass utasítást akövetkező oldalon lévő kódra.

import curses

def main(stdscreen):

curses.init_pair(1, curses.COLOR_BLACK,

curses.COLOR_GREEN)

curses.init_pair(2, curses.COLOR_BLUE,

curses.COLOR_WHITE)

curses.init_pair(3,

curses.COLOR_MAGENTA,curses.COLOR_BLACK)

stdscreen.clear()

stdscreen.addstr(3,1," This is a test

",curses.color_pair(1))

stdscreen.addstr(4,1," This is a test

",curses.color_pair(2))

stdscreen.addstr(5,1," This is a test

",curses.color_pair(3))

stdscreen.refresh()

stdscreen.getch()

curses.wrapper(main)

import curses

import random

class Game1():

def __init__(self):

pass

def main(self,stdscr):

curses.init_pair(1, curses.COLOR_BLACK,

curses.COLOR_GREEN)

curses.init_pair(2, curses.COLOR_BLUE,

curses.COLOR_BLACK)

curses.init_pair(3, curses.COLOR_YELLOW,

curses.COLOR_BLUE)

curses.init_pair(4, curses.COLOR_GREEN,

curses.COLOR_BLUE)

curses.init_pair(5, curses.COLOR_BLACK,

curses.COLOR_RED)

def StartUp(self):

curses.wrapper(self.main)

g = Game1()

g.StartUp()

Page 29: IssuePY02 Hu

full circle magazin Python 2. kötet tartalom ^29

Mostanra már magadtól is kikel lene tudnod találni , hogy ezek-ben a definíciókban mi történik.Ha nem vagyunk biztosak ma-gunkban, akkor megígérem, hogymiközben kitöltjük, minden megvi-lágosodik számunkra.

Lassan kapunk egy működő kó-dot. Ennek el lenére még mindiglétre kel l hoznunk egy pár metó-dust, mielőtt valamire használhat-nánk is. Nézzük meg a betűt jobb-ról balra mozgató rutint:http: //ful lcirclemagazine.pastebin.com/z5CgMAgm

Ez lesz a leghosszabb az egészprogramban, és találkozhatunkegy-két új függvénnyel is. Ascr.delch() metódussal töröl jüka karaktert az adott sor|oszlop-ban. A curses.napms() meg-mondja a pythonnak, hogy vár-jon X ezredmásodpercet (ms).

A rutin logikáját (pszeudo-kódban) a következő oldalon(jobbra fenn) figyelhetjük meg.

Most már képesnek kel l len-ned a kód végigkövetésére. Kétfüggvényre van csak szüksé-günk a helyes működéshez. Azelső az Explode, amit egyelőrea pass utasítással töltünk ki , a

második a ResetForNew. Ezzelaz aktuál is sort, i l letve oszlopotál l ítjuk vissza alapértelmezett-re, beál l ítjuk a DropLetter kap-csolót 0-ra, választunk egy vé-letlen betűt és megjelenésipontot. A következő oldalon kö-zépen jobbra láthatóak.

Még további négy függvény-

re van szükségünk (következőoldal , jobbra lenn). Az első kivá-laszt egy véletlen betűt, a má-sodik pedig egy véletlen megje-lenési pontot. Emlékszünk még,hogy volt a cikksorozat elején arandom modulról szó?

A PickALetterben 65 és 90között generálunk egy számot

(A-tól Z-ig) . Emlékezzünk arra,hogy véletlen egész generálá-sakor meg kel l adnunk egy mi-nimum és maximum számpárt.Ugyanez ál l a PickDropPointesetében is. A random.seed()-et is meghívjuk mindkettőben,ami minden alkalommal inicia-l izál ja a véletlenszám generá-tort. A negyedik rutint

Programozzunk Pythonban ‐ 14. rész# Line Specific Stuff

self.GunLine = 22 #Row where our gun lives

self.GunPosition = 39 #Where the gun starts on GunLine

self.LetterLine = 2 #Where our letter runs right to left

self.ScoreLine = 1 #Where we are going to display the score

self.ScorePosition = 50 #Where the score column is

self.LivesPosition = 65 #Where the lives column is

# Letter Specific Stuff

self.CurrentLetter = "A" #A dummy Holder Variable

self.CurrentLetterPosition = 78 #Where the letter will start on the LetterLine

self.DropPosition = 10 #A dummy Holder Variable

self.DroppingLetter = 0 #Flag ­ Is the letter dropping?

self.CurrentLetterLine = 3 #A dummy Holder Variable

self.LetterWaitCount = 15 #How many times should we loop before actually

working?

# Bullet Specific Stuff

self.Shooting = 0 #Flag ­ Is the gun shooting?

self.BulletRow = self.GunLine ­ 1

self.BulletColumn = self.GunPosition

# Other Stuff

self.LoopCount = 0 #How many loops have we done in MoveLetter

self.GameScore = 0 #Current Game Score

self.Lives = 3 #Default number of lives

self.CurrentColor = 1 #A dummy Holder Variable

self.DecScoreOnMiss = 0 #Set to 1 if you want to decrement the

#score every time the letter hits the

#bottom row

Page 30: IssuePY02 Hu

full circle magazin Python 2. kötet tartalom ^30

Programozzunk Pythonban ‐ 14. részCheckKeys-nek hívják. Ebbenbármi lyen, a   felhasználó általmegnyomott bi l lentyűt figye-lünk, és megfelelően lekezel jüka fegyver mozgatását. Eztegyelőre megíratlanul hagyjuk.Szükségünk lesz még egyCheckForHit nevű metódusra,melyet ismét csak pass-szeltöltünk ki .

def

CheckKeys(self,scrn,keyin):

pass

def CheckForHit(self,scrn):

pass

Létre fogunk hozni egy ap-rócska rutint, ez lesz a játék„agya”. Ezt GameLoopnak fog-juk hívni (következő oldalon,jobbra fenn).

I tt a mögöttes logika az,hogy először a bi l lentyűzetetnodelay(1)-re ál l ítjuk. Ez azt je-lenti , hogy nem várunk bi l len-tyű kombinációkra, és ha mégiskapunk egyet, akkor egyszerű-en eltárol juk későbbi feldolgo-zás cél jából . Ezt követően belé-pünk egy whi le ciklusba, melymindig igaz (1), így a játék ad-dig fog tartani , amíg úgy nemdöntünk, hogy végeztünk. 40ezredmásodpercig várunk,majd elmozdítjuk a betűt és el-

lenőrizzük, hogy a felhasználómegnyomott-e egy gombot. Haez egy „Q” (nagybetűs), vagyaz ESC gomb, akkor megszakít-juk a ciklust és ki lépünk a prog-ramból . Egyébként leel lenőriz-zük, hogy a megnyomott gombjobb, vagy bal nyíl , esetleg szó-köz-e. Később úgy nehezíthet-jük a játékot, hogy csak akkorlőhetünk, ha az aktuál is karak-ternek megfelelő bi l lentyűtnyomtuk le (akárcsak egy egy-szerű, gépelést tanító program-ban). Csak nehogy elfeledjük aQ-t kivenni (a ki lépés gombot).

IF we have waited the correct number of loops THEN

Reset the loop counter

IF we are moving to the left of the screen THEN

Delete the character at the the current row,column.

Sleep for 50 milliseconds

IF the current column is greater than 2 THEN

Decrement the current column

Set the character at the current row,column

IF the current column is at the random column to drop to the bottom THEN

Set the DroppingLetter flag to 1

ELSE

Delete the character at the current row,column

Sleep for 50 milliseconds

IF the current row is less than the line the gun is on THEN

Increment the current row

Set the character at the current row,column

ELSE

IF

Explode (which includes decrementing the score if you wish) and check to

see if we continue.

Pick a new letter and position and start everything over again.

ELSE

Increment the loopcounter

Refresh the screen.

def Explode(self,scrn):

pass

def ResetForNew(self):

self.CurrentLetterLine = self.LetterLine

self.CurrentLetterPosition = 78

self.DroppingLetter = 0

self.PickALetter()

self.PickDropPoint()

def PickALetter(self):

random.seed()

char = random.randint(65,90)

self.CurrentLetter = chr(char)

def PickDropPoint(self):

random.seed()

self.DropPosition = random.randint(3,78)

Page 31: IssuePY02 Hu

full circle magazin Python 2. kötet tartalom ^31

Programozzunk Pythonban ‐ 14. részEgy olyan függvényt is létre

kel l hoznunk, ami az új játékokatelőkészíti . Legyen ennek neveNewGame (jobbra középen).

Szükségünk van még egy rutin-ra (PrintScore), ami kiíratja az ak-tuál is pontszámot és a maradékéletet (jobbra lenn).

Most már csak egy pici kódmaradt hátra (balra lenn) a mainfüggvényben, mely el indítja a já-ték ciklust. További kód lenn lát-ható. Helyezzük el ezt az utolsóinit_pair hívás után.

Végre van egy olyan progra-munk, ami csinál is valamit.Próbáld ki , megvárlak.

I tt a játék már tud választaniegy nagybetűt, azt jobbról bal-ra, majd lefelé mozgatni a kép-ernyőn. Ennek el lenére észre-vehetjük, hogy bármennyiszeris futtatjuk a programot, az elsőbetű mindig „A” és a megjele-nés helye mindig a 10. oszlop.Ez azért van, mert az __init__rutinban megadtunk alapértel-mezett értékeket. Ezt úgy tud-juk kiküszöbölni , hogy egysze-rűen meghívjuk a self.ResetFor-New metódust, mielőtt belép-nénk a main whi le ciklusába.

Ezen a ponton még dolgoz-nunk kel l egy kicsit a „fegyve-rünkön” és a többi segédfügg-vényen. Helyezzük el a kódot

def GameLoop(self,scrn):

test = 1 #Set the loop

while test == 1:

curses.napms(20)

self.MoveLetter(scrn)

keyin =

scrn.getch(self.ScoreLine,self.ScorePosition)

if keyin == ord('Q') or keyin == 27: # 'Q'

or <Esc>

break

else:

self.CheckKeys(scrn,keyin)

self.PrintScore(scrn)

if self.Lives == 0:

break

curses.flushinp()

scrn.clear()

def NewGame(self,scrn):

self.GunChar = curses.ACS_SSBS

scrn.addch(self.GunLine,self.GunPosition,self.GunChar,cu

rses.color_pair(2) | curses.A_BOLD)

scrn.nodelay(1) #Don't wait for a

keystroke...just cache it.

self.ResetForNew()

self.GameScore = 0

self.Lives = 3

self.PrintScore(scrn)

scrn.move(self.ScoreLine,self.ScorePosition)

def PrintScore(self,scrn):

scrn.addstr(self.ScoreLine,self.ScorePosition,"SCORE:

%d" % self.GameScore)

scrn.addstr(self.ScoreLine,self.LivesPosition,"LIVES:

%d" % self.Lives)

stdscr.addstr(11,28,"Welcome to Letter Attack")

stdscr.addstr(13,28,"Press a key to begin....")

stdscr.getch()

stdscr.clear()

PlayLoop = 1

while PlayLoop == 1:

self.NewGame(stdscr)

self.GameLoop(stdscr)

stdscr.nodelay(0)

curses.flushinp()

stdscr.addstr(12,35,"Game Over")

stdscr.addstr(14,23,"Do you want to play

again? (Y/N)")

keyin = stdscr.getch(14,56)

if keyin == ord("N") or keyin == ord("n"):

break

else:

stdscr.clear()

Page 32: IssuePY02 Hu

full circle magazin Python 2. kötet tartalom ^32

Programozzunk Pythonban ‐ 14. rész( jobbra fenn) a Game1 osztály-ban.

A Movegun lekérdezi a fegyveraktuál is pozícióját és elmozdítja amegadott irányba. Az egyetlen do-log, ami új , az a végén lévő addchrutin. Meghívjuk a colorpair(2)-t aszín beál l ításához, majd ugyanittutasítjuk a fegyvert, hogy félkövérlegyen. Ehhez a bitenkénti VAGY-ot(„| ”) használ juk. Ezután meg kel lírnunk a CheckKeys rutint. Cserél-jük le a pass utasítást a következőoldalon, jobbra lent lévő kódra.

Még kel l egy rutin, ami alövedéket „felfelé” mozgatja aképernyőn (balra lenn).

Szükségünk van még párfüggvényre (következő oldal ,jobbra fenn), mielőtt befejezett-nek minősíthetnénk a progra-mot. I tt talá lható a CheckForHités az ExplodeBul let kódja.

Végül , megírjuk az Exploderutint. Helyettesítsük a pass-t akövetkező kóddal (következőoldal , lenn).

Ez már a kész program. A betűksebességének lassításá-hoz/gyorsításához és a nehéz-

ségi szint változtatásához aLetterWaitCount-tal babrálha-tunk egy kicsit. Használhatjukmég a CurrentColort véletlenszínválasztáshoz és a betű szí-nének a négy színpár valame-lyikéhez való véletlen hozzáren-deléséhez.

Gondol j úgy erre, mint egy kisházi feladatra.

Remélem élvezted az e havicikket és ki fogod egy kicsitbővíteni a programot, hogymég játszhatóbb legyen.

def MoveGun(self,scrn,direction):

scrn.addch(self.GunLine,self.GunPosition," ")

if direction == 0: # left

if self.GunPosition > 0:

self.GunPosition ­= 1

elif direction == 1: # right

if self.GunPosition < 79:

self.GunPosition += 1

scrn.addch(self.GunLine,self.GunPosition,self.GunChar,cur

ses.color_pair(2) | curses.A_BOLD)

if keyin == 260: # left arrow ­ NOT on keypad

self.MoveGun(scrn,0)

curses.flushinp() #Flush out the input buffer for safety.

elif keyin == 261: # right arrow ­ NOT on keypad

self.MoveGun(scrn,1)

curses.flushinp() #Flush out the input buffer for safety.

elif keyin == 52: # left arrow ON keypad

self.MoveGun(scrn,0)

curses.flushinp() #Flush out the input buffer for safety.

elif keyin == 54: # right arrow ON keypad

self.MoveGun(scrn,1)

curses.flushinp() #Flush out the input buffer for safety.

elif keyin == 32: #space

if self.Shooting == 0:

self.Shooting = 1

self.BulletColumn = self.GunPosition

scrn.addch(self.BulletRow,self.BulletColumn,"|")

curses.flushinp() #Flush out the input buffer for safety.

def MoveBullet(self,scrn):

scrn.addch(self.BulletRow,self.BulletColumn," ")

if self.BulletRow > self.LetterLine:

self.CheckForHit(scrn)

self.BulletRow ­= 1

scrn.addch(self.BulletRow,self.BulletColumn,"|")

else:

self.CheckForHit(scrn)

scrn.addch(self.BulletRow,self.BulletColumn," ")

self.BulletRow = self.GunLine ­ 1

self.Shooting = 0

Page 33: IssuePY02 Hu

full circle magazin Python 2. kötet tartalom ^33

Programozzunk Pythonban ‐ 14. részdef CheckForHit(self,scrn):

if self.Shooting == 1:

if self.BulletRow == self.CurrentLetterLine:

if self.BulletColumn == self.CurrentLetterPosition:

scrn.addch(self.BulletRow,self.BulletColumn," ")

self.ExplodeBullet(scrn)

self.GameScore +=1

self.ResetForNew()

def ExplodeBullet(self,scrn):

scrn.addch(self.BulletRow,self.BulletColumn,"X",curses.color_pair(5))

scrn.refresh()

curses.napms(200)

scrn.addch(self.BulletRow,self.BulletColumn,"|",curses.color_pair(5))

scrn.refresh()

curses.napms(200)

scrn.addch(self.BulletRow,self.BulletColumn,"­",curses.color_pair(5))

scrn.refresh()

curses.napms(200)

scrn.addch(self.BulletRow,self.BulletColumn,".",curses.color_pair(5))

scrn.refresh()

curses.napms(200)

scrn.addch(self.BulletRow,self.BulletColumn," ",curses.color_pair(5))

scrn.refresh()

curses.napms(200)

scrn.addch(self.CurrentLetterLine,self.CurrentLetterPosition,"X",curses.color_pair(5))

curses.napms(100)

scrn.refresh()

scrn.addch(self.CurrentLetterLine,self.CurrentLetterPosition,"|",curses.color_pair(5))

curses.napms(100)

scrn.refresh()

scrn.addch(self.CurrentLetterLine,self.CurrentLetterPosition,"­",curses.color_pair(5))

curses.napms(100)

scrn.refresh()

scrn.addch(self.CurrentLetterLine,self.CurrentLetterPosition,".",curses.color_pair(5))

curses.napms(100)

scrn.refresh()

scrn.addch(self.CurrentLetterLine,self.CurrentLetterPosition," ")

scrn.addch(self.GunLine,self.GunPosition,self.GunChar,curses.color_pair(2) | curses.A_BOLD)

scrn.refresh()

Greg Walters a RainyDay SolutionsKft. tulajdonosa, amely egy tanács-adó cég Aurorában, Coloradóban,Greg pedig 1 972 óta foglalkozikprogramozással. Szeret főzni, túráz-ni, zenét hallgatni, valamint a csa-ládjával tölteni a szabadidejét.

Mint mindig, a tel jes kód awww.thedesignatedgeek.com,vagy a:http: //ful lcirclemagazine.pastebin.com/DeReeh8mcímen érhető el .

Page 34: IssuePY02 Hu

full circle magazin Python 2. kötet tartalom ^34

HogyanokÍrta: Greg Walters

Programozzunk Pythonban - 1 5. rész

Ehónapban elkezdjük aPygame modul felfede-zését, melyet kifejezet-ten játékok írására

találtak ki . A weblapja:http: //www.pygame.org/.Kapásból idéznék is a Pygamereadme-jéből : „A Pygame egyplatformfüggetlen programmodul , ami olyan multimédiásszoftverek Pythonban való egy-szerűsített megírására szolgál ,mint például a videojátékok is.A Pygame-hez szükségünk vana Python nyelvre, i l letve továb-bi közismert programozásikönyvtárakra.”

A Pygame-et a Synapticonkeresztül a „python-pygame”néven telepíthetjük. Ezt tegyükis meg.

Először beimportál juk aPygame-et (lásd jobbra fenn),majd beál l ítjuk az os.environváltozót az ablakunk középrepozícionálásához. Ezt követőeninicia l izál juk a Pygame ablakot800x600 pixeles felbontásra,i l letve beál l ítjuk a címsort. Vé-gül megjelenítünk mindent és

belépünk egy olyan ciklusba,ami egy bi l lentyű, vagy az egérmegnyomására vár. A screenegy olyan objektum, ami min-den általunk felhasznált elemettárol . Ezt felületnek (surface)nevezzük. Gondol junk erre úgy,mint egy darab papírra, amely-re rajzolni akarunk.

Idáig nem túl izgalmas, dekezdetnek ez is megteszi . Dob-juk fel egy kicsit. A háttérszíntál l ítsuk valami lyen kevésbé sö-tét színre. Találtam egy „color-name” nevezetű programot,amit az Ubuntu Szoftverköz-ponton keresztül fel tudunk te-lepíteni . Segítségével kiválaszt-hatunk egy színt egy „színkeré-ken”, és meg fogja adni ennekRGB - azaz piros, zöld és kék –értékét. Ha nem szeretnénk azelőredefiniá lt Pygame-es szí-nekkel dolgozni , akkor minden-képpen RGB színeket kel l hasz-nálnunk. Ez egy ügyes kis se-gédprogram, mely hasznunkraválhat.

Közvetlenül az import utasí-tások alá helyezzük el a

Background = 208, 202, 104

sort. Ezzel beál l ítjuk a Back-groundot egy cser színre. Kö-vetkezőnek a pygame.display.set_caption sor után írjuk be azalábbiakat:

screen.fill(Background)

pygame.display.update()

A screen.fi l l () metódus amegadott értékre ál l ítja a hát-térszínt. A következő sor, apygame.display.update() pediga képernyőn aktual izál ja a vál-toztatásokat.

Mentsük el a programotpygame1 .py néven és lépjünktovább.

Most a kel lemes kinézetűablakunkban meg fogunk jele-níteni egy szöveget. Ismét azimport utasításainkkal és a hát-térváltozók beál l ításával kez-dünk:

import pygame

from pygame.locals import *

import os

Background = 208, 202, 104

Írjuk meg a betűtípus előtér

#This is the Import

import pygame

from pygame.locals import *

import os

# This will make our game window centered in the screen

os.environ['SDL_VIDEO_CENTERED'] = '1'

# Initialize pygame

pygame.init()

#setup the screen

screen = pygame.display.set_mode((800, 600))

# Set the caption (title bar of the window)

pygame.display.set_caption('Pygame Test #1')

# display the screen and wait for an event

doloop = 1

while doloop:

if pygame.event.wait().type in (KEYDOWN,

MOUSEBUTTONDOWN):

break

Page 35: IssuePY02 Hu

full circle magazin Python 2. kötet tartalom ^35

Programozzunk Pythonban - 1 5. részszínét is:

FontForeground = 255,255,255

# White

Ezután az előző kódot nagy-részt átemel jük (jobbra) .

Ha most futtatjuk, akkor akülalakon semmi változást nemfogunk tapasztalni , mivel kizá-rólag az előtér színét változtat-tuk meg. Írjuk be az alábbi kó-dot a screen.fi l l () sor és a ciklusközé:

font =

pygame.font.Font(None,27)

text = font.render('Here is

some text', True,

FontForeground, Background)

textrect = text.get_rect()

screen.blit(text,textrect)

pygame.display.update()

Mentsünk pygame2.py né-ven és futtassuk. Az ablakunkbal felső sarkában láthatjuk a„Here is some text” fel iratot.

Egyenként nézzük meg az újparancsokat. Először a Font me-tódust hívjuk, melynek két ar-gumentumot adunk át. Az elsőa betűkészlet neve, a másodika betűméret. Egyelőre a 'None'kulcsszó használatával a típus-választást rábízzuk a rendszer-

re, a méretet pedig 27 pontraál l ítjuk.

A következő a font.render()metódus. Ennek négy darab ar-gumentuma van, melyek rend-re: a megjelenítendő szöveg,akarunk-e élsimítást használni(ebben az esetben True, azazigen), végül a betű előtér ésháttér színe.

A következő sor (text.get_rect()) lekér egy befoglaló tég-la lap objektumot, amivel majdkirakjuk a szöveget a képernyő-re. Ez egy fontos lépés, mivelszinte minden más dolog is tég-la lapokkal lesz el intézve. (Kicsitkésőbb vi lágosabb lesz. ) Ezutánbl ittel jük a téglalapot a ki jelző-re, végül frissítünk a szövegmegjelenítéséhez. Na de mi aza bl it és miért akarnánk i lyenfurcsa nevű dolgot használni?Nos, a kifejezés keletkezéseegészen a '70-es évekig nyúl ikvissza, és a Xerox PARC-tól jött(aminek sok, ma használt tech-nológiát köszönhetünk). Erede-ti leg BitBLT volt, ami a Bit (vagybittérkép) Block Transfer rövidí-tése. Ebből lett később a Bl it(mert így sokkal rövidebb).Gyakorlati lag a képeket és szö-vegeket a képernyőre dobjuk.

De mi van akkor, ha a szöve-günket a képernyő közepéreakarnánk igazítani , az első sorhelyett, ahol nem annyira vanszem előtt? A text.get_rect() ésa screen.bl i t között helyezzük elaz alábbi két sort:

textRect.centerx =

screen.get_rect().centerx

textRect.centery =

screen.get_rect().centery

I tt számol juk ki , hogy hovakel l helyezni az objektumot(ami egy felület) , majd atextRect x és y értékét ennekmegfelelően ál l ítjuk be.

Futtassuk le a programot.Most már középen van a szö-

veg, mely a saját felületén he-lyezkedik el . A szöveget afont.set_bold(True) és/vagyfont.set_ital ic(True) (ebben apéldakódban) pygame.font.Fontsor utáni elhelyezésével lehetmódosítani .

Idézzük fel , hogy amikor egybeépített betűtípust ál l ítottunkbe, a „None”-t csak igen rövi-den tárgyaltuk. Tegyük fel ,hogy mi egy valamivel érdeke-sebb típust szeretnénk használ-ni . Mint már előbb is mondtam,a pygame.font.Font() metódus-nak két argumentuma van. Azelső az elérési útja és a betű-készlet fáj l neve, a második abetű mérete. A probléma, mely-

# This will make our game window centered in the screen

os.environ['SDL_VIDEO_CENTERED'] = '1'

# Initialize pygame

pygame.init()

# Setup the screen

screen = pygame.display.set_mode((800, 600))

# Set the caption (title bar of the window)

pygame.display.set_caption('Pygame Test #1')

screen.fill(Background)

pygame.display.update()

# Our Loop

doloop = 1

while doloop:

if pygame.event.wait().type in (KEYDOWN,

MOUSEBUTTONDOWN):

break

Page 36: IssuePY02 Hu

full circle magazin Python 2. kötet tartalom ^36

Programozzunk Pythonban - 1 5. részbe beleütközünk többrétegű.Hogyan határozzuk meg annaka betűtípusnak a tényleges elé-rési útját és fáj lnevét, melyetegy adott rendszeren használniszeretnénk? Szerencsére ren-delkezik a Pygame egy olyanfüggvénnyel , ami mindezt el in-tézi helyettünk, match_font aneve. Itt van egy rövidke kisprogram, ami kiíratja az elérésiútját és fáj lnevét (ebben azesetben) a Courier New típus-nak:

import pygame

from pygame.locals import *

import os

print

pygame.font.match_font('Couri

er New')

Az én rendszeremen a „/usr/share/fonts/truetype/msttcorefonts/cour. ttf” volt a visszaadottérték. Abban az esetben, ha abetűtípus nincs meg, ennek ér-téke „None”. Ha viszont meg-lett, akkor ezt az értéket egyváltozóhoz rendelhetjük éshasználhatjuk az alábbi kifeje-zést:

courier =

pygame.font.match_font('Couri

er New')

font =

pygame.font.Font(courier,27)

Változtassuk meg a progra-mot úgy, hogy tartalmazza eze-ket a sorokat, és futtassuk újra.A lényeg, hogy vagy egy olyanbetűtípust használunk, amirőlTUDJUK, hogy megtalálható afelhasználó rendszerén, vagymel lékel jük azt a programhozés belekódol juk az elérési utat.Más megoldások is lehetsége-sek, de a megtalálásukat meg-hagyom számotokra, és mosttovább lépünk.

Mindez szép és jó, de grafi -kákkal még szebb lenne. Talál -tam egy igen jó tutoria lt, me-lyet Peyton McCol lugh írt a Py-game-hez és úgy döntöttem,hogy egy kicsit módosítom.Szükségünk lesz egy képre, amimászkálni fog a hátterünkön.Ezt a fajta képet sprite-nak ne-vezzük. Használ juk a GIMP-etvagy valami lyen más hasonlóeszközt egy pálcikaember elké-szítéséhez. Nem kel l nagyonszépet készíteni , egy átlagospálcikaember is megteszi . Aztfogom feltételezni , hogy GIMP-el dolgozunk. Készítsünk egy újképet, mely 50x50 pixel méretűés az advanced options alattál l ítsuk a „Fi l l With” opciótTransparency-re. Használ juk a

ceruza eszközt egy Circle(03)-as ecsettel . Rajzol juk meg a kisfiguránkat és mentsük ugyan-abba a mappába, stick.png-ként, amelyben a kódjaink van-nak. Itt van az enyém is. Biz-tosan jobbat is létre tudnátokhozni .

Tudom, nem va-gyok egy művész.Ennek el lenére jólesz arra, amire hiva-

tott. Png-ként mentettük, majda hátteret átlátszóra ál l ítottukahhoz, hogy csak a kis feketevonalak legyenek majd látható-ak – és nem egy fehér vagymásmilyen háttér.

Beszél jünk most arról , hogymit fog a programunk csinálni .Egy olyan Pygame ablakot aka-runk megjeleníteni , ami tartal-mazza a pálcikaembert. Ezenfelül szeretnénk, ha mozogna a

nyíl bi l lentyűkre – feltéve, hanem az ablak szélén vagyunk.Az is jó lenne, ha a program ki-lépne a „q” bi l lentyű megnyo-mására. Nos, a sprite mozgatá-sa könnyűnek hangzik, és az is,de talán mégsem annyira,amennyire szeretnénk. Két tég-la lap létrehozásával kezdünk.Az első magáé a sprite-é, a má-sodik pedig egy ugyanakkora,de üres kép. Bl ittel jük a sprite-ot, majd amikor a felhasználómegnyom egy gombot, az ürestéglalapot rábl ittel jük a sprite-ra, kiszámítjuk az új pozíciót ésvisszabl ittel jük azt az új pozici -óba. Gyakorlati lag hasonlót csi-nálunk, mint múltkor az ábécésjátékban. És ennyi az egész al-kalmazás. Arra elég lesz, hogymegértsük egy kép kirajzolásátés mozgatását.

Tehát, hozzunk létre egy újprogramot és nevezzük el

import pygame

from pygame.locals import *

import os

Background = 0,255,127

os.environ['SDL_VIDEO_CENTERED'] = '1'

pygame.init()

screen = pygame.display.set_mode((800, 600))

pygame.display.set_caption('Pygame Example #4 ­ Sprite')

screen.fill(Background)

Page 37: IssuePY02 Hu

full circle magazin Python 2. kötet tartalom ^3!

Programozzunk Pythonban - 1 5. részpygame4.py-nek. Helyezzük elaz include-okat, amiket ebben acikkben használtunk. Ez alka-lommal egy menta zöld hátte-rünk lesz, azaz a színértékek 0,255 és 127 (lásd előző oldalon).

Ezután létrehozunk egy osz-tályt, ami lekezel i a grafikátvagy a sprite-ot (itt lenn). Eztközvetlenül az importok utánszúrjuk be.

Mit csinál ez az egész? Nos,

kezdjük az __init__ rutinnal . APygame sprite modul ját apygame.sprte.Sprite.__init__sorral inicia l izál juk. Ezután beál-l ítjuk a felületet, melyet screen-nek (képernyő) nevezünk. Ezzelmajd meg tudjuk nézni , hogy asprite lemegy-e a képernyőről .Majd létrehozzuk és beál l ítjukaz üres oldsprite változót, mely-nek a fáj l nevét (és elérési út-ját, ha az nem a program map-pájában van) adjuk át. Ezutánkapunk egy referenciát a sprite-

hoz (self. rect), ami automatiku-san beál l ítja a téglalap széles-ségét és magasságát, i l letve azx és y pozícióit a megadott ér-tékekre.

Az update rutin gyakorlati lagcsak a sprite-ról készít egy má-solatot, majd leel lenőrzi , hogyleesne-e a képernyőről . Haigen, akkor békén hagyja, kü-lönben elmozdítja a megadottmértékkel .

A screen.fi l l utasítás után he-lyezzük el a következő oldalon(jobbra) látható kódot.

I tt létrehozunk egy példánytaz osztályunkból , amit charac-ter-nek hívunk. Ezt követőenbl ittel jük a sprite-ot. Létrehoz-zuk az üres sprite téglalapot éskitöltjük a háttérszínnel , majdfrissítjük a felületünket és belé-pünk a ciklusba.

Addig, amíg a DoLoop 1-elegyenlő, a ciklusban maradunk.A pygame.event.get()-et hasz-nál juk a karakterek beolvasásá-hoz. Ezután az esemény típusá-hoz párosítjuk őket. Ha ez QUIT,akkor ki lépünk. Ha KEYDOWN,akkor feldolgozzuk. Megnézzüka kapott karakter értékét ésösszehasonlítjuk a Pygame-bendefiniá lt konstansokkal . Ezutánmeghívjuk az osztályunk up-date rutinját. Figyel jük meg,hogy egyszerűen továbbadjuk apixelek x- és y-tengelyen valóelmozdulásainak l istáját. Tízpixel lel töltjük fel (pozitívokkaljobb vagy le esetben, negatí-vokkal balra és fel esetben). Haa karakter „q”-val egyenlő, ak-kor a DoLoopot 0-ra ál l ítjuk, ígylépvén ki a ciklusból . Kizárólagezek után bl ittel jük a sprite-

class Sprite(pygame.sprite.Sprite):

def __init__(self, position):

pygame.sprite.Sprite.__init__(self)

# Save a copy of the screen's rectangle

self.screen = pygame.display.get_surface().get_rect()

# Create a variable to store the previous position of the sprite

self.oldsprite = (0, 0, 0, 0)

self.image = pygame.image.load('stick3.png')

self.rect = self.image.get_rect()

self.rect.x = position[0]

self.rect.y = position[1]

def update(self, amount):

# Make a copy of the current rectangle for use in erasing

self.oldsprite = self.rect

# Move the rectangle by the specified amount

self.rect = self.rect.move(amount)

# Check to see if we are off the screen

if self.rect.x < 0:

self.rect.x = 0

elif self.rect.x > (self.screen.width ­ self.rect.width):

self.rect.x = self.screen.width ­ self.rect.width

if self.rect.y < 0:

self.rect.y = 0

elif self.rect.y > (self.screen.height ­ self.rect.height):

self.rect.y = self.screen.height ­ self.rect.height

Page 38: IssuePY02 Hu

full circle magazin Python 2. kötet tartalom ^3!

unkat az új pozícióba és frissí-tünk – de ebben az esetbencsak a két téglalapot, az üresés aktív sprite-okat, így temér-dek időt és számítási kapacitásttakarítunk meg.

Mint mindig, a tel jes kód awww.thedesignatedgeek.comoldalon, vagy ahttp: //ful lcirclemagazine.pastebin.com/DvSpZbajcímen érhető el .

Sok minden van még, amit aPygame-el meg tudunk oldani .Azt javaslom, hogy látogassukmeg a honlapjukat és keressükmeg a referenciaoldalt(http: //www.pygame.org/docs/ref/index.html) .

Ezen felül még mások általkészített játékokat is megte-kinthetünk.

Következő alkalommal egyrégi játékommal picit mélyebb-re ásunk a Pygame-ben.Egy NAGYON régi játékommal.

Programozzunk Pythonban - 1 5. rész

character = Sprite((screen.get_rect().x, screen.get_rect().y))

screen.blit(character.image, character.rect)

# Create a Surface the size of our character

blank = pygame.Surface((character.rect.width, character.rect.height))

blank.fill(Background)

pygame.display.update()

DoLoop = 1

while DoLoop:

for event in pygame.event.get():

if event.type == pygame.QUIT:

sys.exit()

# Check for movement

elif event.type == pygame.KEYDOWN:

if event.key == pygame.K_LEFT:

character.update([­10, 0])

elif event.key == pygame.K_UP:

character.update([0, ­10])

elif event.key == pygame.K_RIGHT:

character.update([10, 0])

elif event.key == pygame.K_DOWN:

character.update([0, 10])

elif event.key == pygame.K_q:

DoLoop = 0

# Erase the old position by putting our blank Surface on it

screen.blit(blank, character.oldsprite)

# Draw the new position

screen.blit(character.image, character.rect)

# Update ONLY the modified areas of the screen

pygame.display.update([character.oldsprite, character.rect])

Greg Walters a RainyDay SolutionsKft. tulajdonosa, amely egy tanács-adó cég Aurorában, Coloradóban,Greg pedig 1 972 óta foglalkozikprogramozással. Szeret főzni, túráz-ni, zenét hallgatni, valamint a csa-ládjával tölteni a szabadidejét.

Page 39: IssuePY02 Hu

full circle magazin Python 2. kötet tartalom ^39

HHooggyyaannookkÍrta: Greg Walters

PPrrooggrraammoozzzzuunnkk PPyytthhoonnbbaann -- 11 66.. rréésszz

N emrég megígértemvalakinek, hogy meg-tárgyal juk a Python2.x és 3.x verziói kö-

zötti különbségeket. Legutóbbpedig azt mondtam, hogy foly-tatjuk pygame-es programozá-sunkat. Ennek el lenére úgyérzem, hogy be kel l tartanomaz ígéretemet, azaz majd csaka legközelebbi alkalommal fo-gunk a pygame-el foglalkozni .

A Python 3.x verziójábansok változás történt. Minderrőlsok információ érhető el aWeben, melyek közül néhányl inkjét a cikk végén megtalál -hatjátok. Ennek el lenére sokaggodalom van a váltás körül .Most csak azokra a különbsé-gekre fogunk összpontosítani ,melyek kihatnak az általunk ta-nultakra.

Vágjunk is bele.

PRINT

Már korábban is utaltam rá,hogy az egyik legnagyobb különb-ség, a print utasítás használatábanvan. 2.x alatt egyszerűen írhattukaz alábbit:

print “This is a test”

és végeztünk is. Ha viszont 3.xalatt próbálkozunk ugyanezzel ,akkor a jobbra fenn lévő hiba-üzenetet kapjuk.

Ez persze nem jó nekünk.Ahhoz, hogy használhassuk aprint utasítást, a kiírandó szö-veget az alábbi módon záróje-lek közé kel l rakni :print(“this is a test”)

Nem egy hatalmas változás,de olyan, amire oda kel l figyel-ni . Már azzal fel tudunk készül-ni a váltásra, ha ezt a szintax-ist használ juk 2.x alatt is.

Formázás és változóbehelyettesítés

A formázás és a változó be-helyettesítés is megváltozott.2.x alatt a lenti példában látha-tó dolgokat használtuk, i l letve a3.1 alatt is a megfelelő ered-ményt kapjuk. Azonban ez ha-marosan meg fog változni, merta „%s” és „%d” formázó függ-vények el fognak tűnni. Az újmódszer a „{x}” helyettesítőutasítást fogja használni , melyeta régi példa alatt láthatunk.

Nekem könnyebben olvas-

hatónak tűnik. Továbbá azalábbihoz hasonló dolgokat istudunk majd csinálni :

>>> print("Hello {0}. I'm

glad you are here at

{1}".format("Fred","MySite.c

om"))

Hello Fred. I'm glad you

are here at MySite.com

>>>

Emlékezzünk arra, hogy bárhasználhatjuk a „%s”-et és vál-tozatait, de ezek egy idő múlvatel jesen ki fognak veszni anyelvből .

Számok

Python 2.x alatt, ha ezt ír-tuk:x = 5/2.0

>>> print "This is a test"

File "<stdin>", line 1

print "This is a test"

^

SyntaxError: invalid syntax

>>>

>>> months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec']

>>> print "You selected month %s" % months[3]

You selected month Apr

>>>

>>> months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec']

>>> print("You selected month {0}".format(months[3]))

You selected month Apr

>>>

Régi

Új

Page 40: IssuePY02 Hu

full circle magazin Python 2. kötet tartalom ^40

Programozzunk Pythonban - 1 6. rész

akkor x tartalma 2.5 lett volna.De viszont azx = 5/2

kifejezésben a levágás miatt 2maradt volna. 3.x alatt az:x = 5/2

kifejezéssel már 2.5-öt kapunk.A levágáshoz az alábbit kel lhasználni :x = 5//2

Input

Régebben volt szó egy, afelhasználó válaszait kezelő, ésa raw_input()-ot használó me-nürendszerről . Valami i lyesmivolt:

response = raw_input('Enter

a selection ­> ')

Ez rendben is van 2.x alatt.Viszont 3.x alatt a következőtkapjuk:

Traceback (most recent call

last):

File "<stdin>", line 1, in

<module>

NameError: name 'raw_input'

is not defined

Ez nem egy kritikus problé-ma. A raw_input() metódus az

input()-ra lett cserélve. Egysze-rűen változtassuk meg a sort:

response = input('Enter a

selection ­> ')

és rendben fog működni .

Nem egyenlő

2.x alatt az egyenlőtlenségtesztelésére a „<>” operátorthasználtuk. Ez azonban márnem megengedett 3.x alatt. Az

új változat a „!=”.

RégebbiprogramokkonvertálásaPython 3.x alá

A Python 3.x-et egy olyansegédprogrammal kapjuk, amisegít az alkalmazások 2.x-ről3.x-re való konvertálásában. Eznem mindig működik, de sokesetben közelebb kerülünk a

kívánt végeredményhez. Akonverziós programot (logiku-san) „2to3”-nek nevezik. Ve-gyünk egy egyszerű progra-mot. A lenn található példamég régebbről – egészen pon-tosan a 3. részből – származik.

#pprint1.py

#Example of semi­useful functions

def TopOrBottom(character,width):

# width is total width of returned line

return '%s%s%s' % ('+',(character * (width­2)),'+')

def Fmt(val1,leftbit,val2,rightbit):

# prints two values padded with spaces

# val1 is thing to print on left, val2 is thing to print on right

# leftbit is width of left portion, rightbit is width of right portion

part2 = '%.2f' % val2

return '%s%s%s%s' % ('| ',val1.ljust(leftbit­2,' '),part2.rjust(rightbit­2,' '), |')

# Define the prices of each item

item1 = 3.00

item2 = 15.00

# Now print everything out...

print TopOrBottom('=',40)

print Fmt('Item 1',30,item1,10)

print Fmt('Item 2',30,item2,10)

print TopOrBottom('­',40)

print Fmt('Total',30,item1+item2,10)

print TopOrBottom('=',40)

+======================================+

| Item 1 3.00 |

| Item 2 15.00 |

+­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­+

| Total 18.00 |

+======================================+

Script terminated.

Page 41: IssuePY02 Hu

full circle magazin Python 2. kötet tartalom ^41

Amikor 2.x alatt futtatjuk, azelőző oldalon jobbra fent lévőkimenetet kapjuk.

De természetesen, a 3.x-elnem fog működni .

File "pprint1.py", line 18

print

TopOrBottom('=',40)

^

SyntaxError: invalid syntax

A problémát a konverziósprogrammal próbál juk orvosol-ni . Mielőtt belevágnánk, érde-mes egy biztonsági másolatotlétrehozni a konvertálandó al-kalamazásról . Én ezt a fáj l má-solásával oldom meg, úgy hogy

a végére biggyesztem a „v3”-at:

cp pprint1.py pprint1v3.py

Több fajta módszer van aprogram futtatására. A legegy-szerűbb, ha megkerestetjük aprogrammal a hibákat. Ezt bal-ra lent láthatjuk.

Figyel jük meg, hogy az ere-deti forráskód nem változott. Aváltozások fáj lba való menté-séhez a „-w” paramétert kel lhasználnunk. Ennek eredmé-nyét jobbra lenn talál juk.

Azt is észrevehetjük, hogy akimenetek megegyeznek. Ezalkalommal a forrásfáj lunk

> 2to3 pprint1v3.py

RefactoringTool: Skipping implicit fixer: buffer

RefactoringTool: Skipping implicit fixer: idioms

RefactoringTool: Skipping implicit fixer: set_literal

RefactoringTool: Skipping implicit fixer: ws_comma

RefactoringTool: Refactored pprint1v3.py

­­­ pprint1v3.py (original)

+++ pprint1v3.py (refactored)

@@ ­15,9 +15,9 @@

item1 = 3.00

item2 = 15.00

# Now print everything out...

­print TopOrBottom('=',40)

­print Fmt('Item 1',30,item1,10)

­print Fmt('Item 2',30,item2,10)

­print TopOrBottom('­',40)

­print Fmt('Total',30,item1+item2,10)

­print TopOrBottom('=',40)

+print(TopOrBottom('=',40))

+print(Fmt('Item 1',30,item1,10))

+print(Fmt('Item 2',30,item2,10))

+print(TopOrBottom('­',40))

+print(Fmt('Total',30,item1+item2,10))

+print(TopOrBottom('=',40))

RefactoringTool: Files that need to be modified:

RefactoringTool: pprint1v3.py

> 2to3 ­w pprint1v3.py

RefactoringTool: Skipping implicit fixer: buffer

RefactoringTool: Skipping implicit fixer: idioms

RefactoringTool: Skipping implicit fixer: set_literal

RefactoringTool: Skipping implicit fixer: ws_comma

RefactoringTool: Refactored pprint1v3.py

­­­ pprint1v3.py (original)

+++ pprint1v3.py (refactored)

@@ ­15,9 +15,9 @@

item1 = 3.00

item2 = 15.00

# Now print everything out...

­print TopOrBottom('=',40)

­print Fmt('Item 1',30,item1,10)

­print Fmt('Item 2',30,item2,10)

­print TopOrBottom('­',40)

­print Fmt('Total',30,item1+item2,10)

­print TopOrBottom('=',40)

+print(TopOrBottom('=',40))

+print(Fmt('Item 1',30,item1,10))

+print(Fmt('Item 2',30,item2,10))

+print(TopOrBottom('­',40))

+print(Fmt('Total',30,item1+item2,10))

+print(TopOrBottom('=',40))

RefactoringTool: Files that were modified:

RefactoringTool: pprint1v3.py

Programozzunk Pythonban - 1 6. rész

Page 42: IssuePY02 Hu

full circle magazin Python 2. kötet tartalom ^42

viszont „version 3.x compatib-le” fáj l lá változott (jobbra).

A program most már műkö-dik 3.x alatt is, valamint, mivelegy elég egyszerű programrólvan szó, a 2.x verzióval is kom-patibi l is maradt.

Most azonnal váltsak3.x-re?

A legtöbb probléma a többinyelv változásánál is előfordul .A szintaxis átalakul minden e-gyes új verzióval . A rövidíté-sek, mint += és -= a semmibőlhul lanak elénk, hogy megköny-nyítsék életünket.

Hogy mekkora a hátránya a3.x-re való migrálásnak? Nos,van egy kicsi . Sok olyan függ-vénykönyvtár van, ami még3.x alá nem érhető el . Olyandolgok, mint például a Muta-gen – melyet néhány számmalkorábban már használtunk –sem használható még. Annakel lenére, hogy mindezek fogósérvek, nem jelentik azt, hogyfel kel l adnunk a Python v3.x-et.

Az én javaslatom az lenne,hogy kezdjünk el a helyes 3.x-ás szintaxissal kódolni . A Py-thon 2.6 támogat majdnem

minden olyan dolgot, melyet3.x-ben használnánk. Ezzel amódszerrel készen fogunk ál lnia 3.x-re való váltáshoz, amikorannak el fog jönni az ideje. Haviszont meg tudunk lenni aszabványos modulokkal , akkorakár bele is vághatunk. Más-részt, ha a határokat akarnánkfeszegetni , érdemes addig vár-ni , amíg a modulok fel nemzárkóznak (mert biztosan felfognak).

Lentebb pár l inket találunk,amikről úgy gondoltam, hogyhasznosak lehetnek. A legelsőa 2to3 használati útmutatója. A

második egy 4 oldalas puska,amit elég jó referenciának ta-lá ltam. A harmadik pedig egyolyan könyv a Pythonról , amit alegjobbnak tartok. (Legalábbisaddig, amíg meg nem írom asajátomat. )

Találkozzunk legközelebb is!

Linkek

A 2to3 használata:

http: //docs.python.org/l ibrary/2to3.html

Moving from Python 2 toPython 3 (A 4 oldalas puska)http: //ptgmedia.pearsoncmg.com/imprint_downloads/informit/promotions/python/python2python3.pdf

Dive into Python 3http: //diveintopython3.org/

#pprint1.py

#Example of semi­useful functions

def TopOrBottom(character,width):

# width is total width of returned line

return '%s%s%s' % ('+',(character * (width­2)),'+')

def Fmt(val1,leftbit,val2,rightbit):

# prints two values padded with spaces

# val1 is thing to print on left, val2 is thing to print on right

# leftbit is width of left portion, rightbit is width of right portion

part2 = '%.2f' % val2

return '%s%s%s%s' % ('| ',val1.ljust(leftbit­2,' '),part2.rjust(rightbit­2,' '),' |')

# Define the prices of each item

item1 = 3.00

item2 = 15.00

# Now print everything out...

print(TopOrBottom('=',40))

print(Fmt('Item 1',30,item1,10))

print(Fmt('Item 2',30,item2,10))

print(TopOrBottom('­',40))

print(Fmt('Total',30,item1+item2,10))

print(TopOrBottom('=',40))

Programozzunk Pythonban - 1 6. rész

Page 43: IssuePY02 Hu

full circle magazin Python 2. kötet tartalom ^43

KKöözzrreemműűkkööddnnééll??A Full Circle Csapata

Szerkesztő - Ronnie [email protected] - Rob [email protected]ációs felelős - Robert [email protected] - Robert [email protected]

Ha hírt szeretnél közölni, megteheted a következő címen: [email protected]

Véleményed és Linuxos tapasztalataidat ide küldd: [email protected]

Hardver és szoftver elemzéseket ide küldhetsz: [email protected]

Kérdéseket a „Kérdések és Válaszok” rovatba ide küldd: [email protected]

Az én asztalom képeit ide küldd: [email protected]

... vagy látogasd meg fórumunkat: www.fullcirclemagazine.org

A FULL CIRCLE-NEK SZÜKSÉGE VAN RÁD!Egy magazin, ahogy a Full Circle is, nem magazin cikkek nélkül. Osszátok meg velünk véle-ményeiteket, desktopjaitok kinézetét és történeteiteket. Szükségünk van a Fókuszban ro-vathoz játékok, programok és hardverek áttekintő leírására, a Hogyanok rovatbanszereplő cikkekre (K/X/Ubuntu témával) , ezenkívül, ha bármilyen kérdés, javaslat merül felbennetek, nyugodtan küldjétek a következő címre: [email protected]

Az olvasóközönségtől folyamatosan várjuk a magazinban megjelenítendő új cikkeket!További információkat a cikkek irányvonalairól, ötletekről és a kiadások fordításairól ahttp://wiki.ubuntu.com/UbuntuMagazine wiki oldalunkon olvashatsz.Cikkeidet az alábbi címre várjuk: [email protected] fordítócsapat wiki oldalát itt találod:https://wiki.ubuntu.com/UbuntuMagazine/TranslateFullCircle/HungarianA magazin eddig megjelent magyar fordításait innen töltheted le: http://www.fullcircle.huHa email-t akarsz írni a magyar fordítócsapatnak, akkor erre a címre küldd:[email protected]

Köszönet a Canonical-nek ésa fordítócsapatoknakvilágszerte, továbbá Thors-ten Wilms-nek a jelenlegiFull Circle logóért.

Palotás AnnaKovács Roland Attila

Tömösközi Máté Ferenc

Full Circle MagazinMagyar Fordítócsapat

Szerkesztő, korrektor:Heim Tibor

Koordinátor:Pércsy KornélFordítók: