43

full circledl.fullcirclemagazine.org/issuePY02_hu.pdf · 2018. 4. 3. · ,;22)/8)2+3'-'@/4 ?:.54 1j:+: n;ln;fig9 '?a #;

  • Upload
    others

  • View
    3

  • Download
    0

Embed Size (px)

Citation preview

  • 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

  • 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!

    http://creativecommons.org/licenses/by-sa/3.0/

  • 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

  • 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 importjoin,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 subfolders),\n''\tread the id3 tags, and write that information to a SQLite database.\n\n''Usage:\n''\t{0} \n''\t WHERE 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)

  • 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 connectionglobal 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 toexist...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!")

    http://pastebin.com/CegsAXjW

  • 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 beprinted with {0} number ofstatements”).format(replacement 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.

    http://pastebin.com/rFf4Gm7E

  • 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:

    Data

    HereNode 2data

    more

    data

    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:

    DataHereNode 2datamoredata

    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 . ), 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 , és 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

  • 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:

    importelementtree.ElementTree as ET

    tree =ET.parse('xmlsample1.xml')

    ET.dump(tree)

    Amikor a tesztprogramotfuttatjuk, valami i lyesmit kel lenekapnunk:

    SamanthaPharohFemale123 Main St.DenverColorado

    SteveLevonMale332120 Arapahoe Blvd.DenverColorado

    /usr/bin/python u"/home/greg/Documents/articles/xml/reader1.py"

    SamanthaPharohFemale123 Main St.DenverColorado

    SteveLevonMale332120 Arapahoe

    Blvd.DenverColorado

    http://effbot.org/downloads/#elementtree

  • 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:

    importelementtree.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/articles/xml/reader1.py"

    Element: firstname Data:SamanthaElement: lastname Data:PharohElement: gender Data:FemaleElement: address Data: 123Main St.Element: city Data: DenverElement: state Data:Colorado

    Element: firstname Data:SteveElement: lastname Data:LevonElement: gender Data: MaleElement: address Data:332120 Arapahoe Blvd.Element: city Data: DenverElement: 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-

    Open Cache: UnrestrictedCache Type: NormalCache Size: NormalDifficulty: 1.5Terrain : 2.0]]>

    Geocachehttp://www.navicache.com/cgi

    bin/db/displaycache2.pl?CacheID=11436

    Navicache fáj l

    http://www.geocaching.com/http://navicache.com/

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

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

    Open Cache: Unrestricted

    Cache Type: Normal

    Cache Size: Normal

    Difficulty: 1.5

    Terrain : 2.0]]>

    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:endposition]

    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 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:]

  • 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 = valueelif name == "lon":

    Lon = valueelif w1.tag == "type":

    GType = w1.textelif w1.tag == "link":

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

    Info = valueLink = w1.text

    print "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: ",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.

  • 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

    http://www.wunderground.comhttp://wiki.wunderground.com/index.php/API_-_XMLhttp://api.wunderground.com/auto/wui/geo/WXCurrentObXML/index.xml?query=80013http://api.wunderground.com/auto/wui/geo/ForecastXML/index.xml?query=80013

  • 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 importElementTree 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.pyReturns current conditions, forecast and alerts for agiven zipcode from WeatherUnderground.com.Usage: python wonderground.py [options]Options:h, help Show this helpl, location City,State to usez, 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 aslocation)"""

    class CurrentInfo:"""This routine retrieves the current condition xml datafrom WeatherUnderground.combased off of the zip code or Airport Code...currently tested only with Zip Code and Airport codeFor location,if zip code use something like 80013 (no quotes)if airport use something like "KDEN" (use doublequotes)if city/state (US) use something like "Aurora,%20CO" or“Aurora,CO” (use doublequotes)if city/country, use something like "London,%20England"(use doublequotes)"""def getCurrents(self,debuglevel,Location):pass

    def output(self):passdef DoIt(self,Location):pass

    #=========================================# END OF CLASS CurrentInfo()#=========================================

  • 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 = 80013try: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 = argelif opt in ("z", "zip"):location = argprint "Location = %s" % locationcurrents = CurrentInfo()currents.DoIt(location)

    #============================================# Main loop#============================================if __name__ == "__main__":

    main(sys.argv[1:])

  • 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 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" % Locationtry:CurrentConditions ='http://api.wunderground.com/auto/wui/geo/WXCurrentObXML/index.xml?query=%s' % Locationurllib.socket.setdefaulttimeout(8)usock = urllib.urlopen(CurrentConditions)tree = ET.parse(usock)usock.close()except:print 'ERROR Current Conditions Could not getinformation from server...'if debuglevel > 0:print Locationsys.exit(2)# Get Display Locationfor loc in tree.findall("//full"):self.location = loc.text# Get Observation timefor tim in tree.findall("//observation_time"):self.obtime = tim.text# Get Current conditionsfor weather in tree.findall("//weather"):self.we = weather.text# Get Tempfor TempF in tree.findall("//temperature_string"):self.tmpB = TempF.text#Get Humidityfor hum in tree.findall("//relative_humidity"):self.relhum = hum.text# Get Wind infofor windstring in tree.findall("//wind_string"):self.winds = windstring.text# Get Barometric Pressurefor pressure in tree.findall("//pressure_string"):self.baroB = pressure.text

    getCurrents rutin

    Aurora, COAuroraCOColoradoUSUS8001339.65906525104.781059271706.00000000 ft

    http://docs.python.org/library/urllib.html

  • 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 címkehelyett a 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.locationprint self.obtimeprint 'Current Weather %s' % self.weprint 'Current Temp %s' % self.tmpBprint 'Barometric Pressure %s' % self.baroBprint 'Relative Humidity %s' % self.relhumprint 'Winds %s' % self.winds

    Location = 80013Weather Information From Wunderground.comWeather info for Aurora, ColoradoLast Updated on May 3, 11:55 AM MDTCurrent Weather Partly CloudyCurrent Temp 57 F (14 C)Barometric Pressure 29.92 in (1013 mb)Relative Humidity 25%Winds From the WNW at 10 MPHScript 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.

    http://pastebin.com/4ibJGm74

  • 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 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() 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-

    3:31 PM MDT2−

    1nt_cloudy+Tonight−Mostly cloudy with a 20

    percent chance of thunderstorms in the evening...thenpartly cloudy after midnight. Lows in the mid 40s.Southeast winds 10 to 15 mph shifting to the south aftermidnight.

    +

    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

    http://api.wunderground.com/auto/wui/geo/ForecastXML/index.xml?query=80013

  • 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 részé-re, mely jobbra látható.

    Van egy 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 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 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 importElementTree 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ó.

    1−

    12757068259:00 PM MDT9:00 PM MDT on June 04, 20104620101542100251June

    FridayPMMDTAmerica/Denver

    9233

    5814

    Partly Cloudypartlycloudy+partlycloudy10

    ...

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

    Programozzunk Pythonban ‐ 12. részclass ForecastInfo:

    def __init__(self):self.forecastText = [] # Today/tonight forecast

    informationself.Title = [] # Today/tonightself.date = ''self.icon = [] # Icon to use for conditions

    today/tonightself.periods = 0self.period = 0

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

    forecastself.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 textself.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' % locationurllib.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)

  • 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 elemben lévőösszes adatot. Ezzel megleszminden információ az adottcsoportból . Ezután megkeres-sük a és 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 elemnek két példányavan. A alatt lévőalelemek a , ,, és .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:

    defDoIt(self,Location,US,IncludeToday,Output):

    self.GetForecastData(Location)

    self.output(US,IncludeToday,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.

    http://pastebin.com/wsSXMXQx

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

    Programozzunk Pythonban ‐ 12. részdef output(self,US,IncludeToday,Output):

    # US takes 0,1 or 2# 0 = Centigrade# 1 = Fahrenheit# 2 = both (if available)# Now print it allif 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 = 0else:

    startRange = 1for 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%% chanceof precipitation.' %(self.extConditions[c],int(self.extpop[c]))

  • 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 cursesmyscreen = curses.initscr()myscreen.border(0)myscreen.addstr(12, 25, "See Curses, See Curses Run!")myscreen.refresh()myscreen.getch()curses.endwin()

  • 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# CursesExample2import 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 Recipes2 Search for a recipe3 Show a Recipe4 Delete a recipe5 Add a recipe6 Print a recipe0 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()

  • 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.initscreenLogicLoop

    ShowMainMenu # Show the main menuMainInKey # This is our main input handling routine

    While Key != 0:If Key == 1:

    ShowAllRecipesMenu # Show the All Recipes MenuInkey1 # Do the input routines for thisShowMainMenu # Show the main menu

    If Key == 2:SearchForARecipeMenu # Show the Search for a Recipe MenuInKey2 # Do the input routines for this optionShowMainMenu # Show the main menu again

    If Key == 3:ShowARecipeMenu # Show the Show a recipe menu routineInKey3 # Do the input routine for this routineShowMainMenu # Show the main menu again

    … # And so on and so oncurses.endwin() # Restore the terminal

    # MAIN LOOPtry:

    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()

  • 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

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

    http://pastebin.com/ELuZ3T4Phttp://docs.python.org/library/curses.htmlhttp://pastebin.com/Pk74fLF3http://fullcirclemagazine.pastebin.com

  • 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],[foregroundcolor],[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 cursestry:

    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()

  • 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 cursesdef 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 cursesimport random

    class Game1():def __init__(self):

    passdef 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()

  • 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 Stuffself.GunLine = 22 #Row where our gun livesself.GunPosition = 39 #Where the gun starts on GunLineself.LetterLine = 2 #Where our letter runs right to leftself.ScoreLine = 1 #Where we are going to display the scoreself.ScorePosition = 50 #Where the score column isself.LivesPosition = 65 #Where the lives column is

    # Letter Specific Stuffself.CurrentLetter = "A" #A dummy Holder Variableself.CurrentLetterPosition = 78 #Where the letter will start on the LetterLineself.DropPosition = 10 #A dummy Holder Variableself.DroppingLetter = 0 #Flag Is the letter dropping?self.CurrentLetterLine = 3 #A dummy Holder Variableself.LetterWaitCount = 15 #How many times should we loop before actually

    working?

    # Bullet Specific Stuffself.Shooting = 0 #Flag Is the gun shooting?self.BulletRow = self.GunLine 1self.BulletColumn = self.GunPosition

    # Other Stuffself.LoopCount = 0 #How many loops have we done in MoveLetterself.GameScore = 0 #Current Game Scoreself.Lives = 3 #Default number of livesself.CurrentColor = 1 #A dummy Holder Variableself.DecScoreOnMiss = 0 #Set to 1 if you want to decrement the

    #score every time the letter hits the#bottom row

    http://fullcirclemagazine.pastebin.com/z5CgMAgm

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

    defCheckKeys(self,scrn,keyin):

    passdef 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 THENReset the loop counterIF we are moving to the left of the screen THENDelete the character at the the current row,column.Sleep for 50 millisecondsIF the current column is greater than 2 THEN

    Decrement the current columnSet the character at the current row,columnIF the current column is at the random column to drop to the bottom THEN

    Set the DroppingLetter flag to 1ELSEDelete the character at the current row,columnSleep for 50 millisecondsIF the current row is less than the line the gun is on THEN

    Increment the current rowSet the character at the current row,column

    ELSEIFExplode (which includes decrementing the score if you wish) and check tosee if we continue.Pick a new letter and position and start everything over again.

    ELSEIncrement the loopcounter

    Refresh the screen.

    def Explode(self,scrn):pass

    def ResetForNew(self):self.CurrentLetterLine = self.LetterLineself.CurrentLetterPosition = 78self.DroppingLetter = 0self.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)

  • 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 loopwhile test == 1:

    curses.napms(20)self.MoveLetter(scrn)keyin =

    scrn.getch(self.ScoreLine,self.ScorePosition)if keyin == ord('Q') or keyin == 27: # 'Q'

    or break

    else:self.CheckKeys(scrn,keyin)

    self.PrintScore(scrn)if self.Lives == 0:

    breakcurses.flushinp()scrn.clear()

    def NewGame(self,scrn):self.GunChar = curses.ACS_SSBS

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

    scrn.nodelay(1) #Don't wait for akeystroke...just cache it.

    self.ResetForNew()self.GameScore = 0self.Lives = 3self.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 = 1while 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"):

    breakelse:

    stdscr.clear()

  • 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: # rightif self.GunPosition < 79:

    self.GunPosition += 1

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

    if keyin == 260: # left arrow NOT on keypadself.MoveGun(scrn,0)curses.flushinp() #Flush out the input buffer for safety.

    elif keyin == 261: # right arrow NOT on keypadself.MoveGun(scrn,1)curses.flushinp() #Flush out the input buffer for safety.

    elif keyin == 52: # left arrow ON keypadself.MoveGun(scrn,0)curses.flushinp() #Flush out the input buffer for safety.

    elif keyin == 54: # right arrow ON keypadself.MoveGun(scrn,1)curses.flushinp() #Flush out the input buffer for safety.

    elif keyin == 32: #spaceif self.Shooting == 0:

    self.Shooting = 1self.BulletColumn = self.GunPositionscrn.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 1self.Shooting = 0

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

    Programoz