28
Kas

Bu dersimizde simülasyonumuzu geliştirmeye devam ediyoruz.

Düşen topların bir engelle karşılasmasını sağlayacağız.

def sabit_cizgi_ekle(space):
    govde = pymunk.Body(pymunk.inf, pymunk.inf)
    govde.position = (300,200)
    l1 = pymunk.Segment(govde, (-200, 0), (200.0, 0.0), 5.0)
    l2 = pymunk.Segment(govde, (-200.0, 0), (-200.0, 50.0), 5.0)
    l3 = pymunk.Segment(govde, (200.0, 0), (200.0, 50.0), 5.0)

    space.add_static(l1, l2,l3)
    return l1,l2,l3

def to_pygame(p):
    """pymunk-pygame koordinat düzenlemesi yapar."""
    return int(p.x), int(-p.y+600)

def cizgileri_ciz(ekran, cizgiler):
    for cizgi in cizgiler:
        body = cizgi.body
        pv1 = body.position + cizgi.a.rotated(body.angle)
        pv2 = body.position + cizgi.b.rotated(body.angle)
        p1 = to_pygame(pv1)
        p2 = to_pygame(pv2)
        pygame.draw.line(ekran, THECOLORS["red"], p1, p2)

sabit_cizgi_ekle() fonksiyonuna yine space adında bir parametre veriyoruz. Fonksyionumuzda bir gövde tanımladık ve kütlesiyle momentini pymunk.inf değişkeniyle sonsuz yaptık. Bir nevi duvara monteleme işlemide denebilir sanırım… Gövdemizin pozisyonunu vektörel olarak 300×200 olarak belirledik. l1, l2, l3 değişkenlerine Segment nesnesi tanımladık. İlk parametreyle gövdesini diğer iki parametresini pygame.draw.line() da gördüğümüz gibi çizgi koordinatlarını belirledik. Son koordinat ise çizginin çapını belirliyor; daha doğrusu kalınlığı diyebiliriz…

Sabit olarak ekleyeceğimiz nesneleri Space sınıfımızın add_static() methodu ile ekliyoruz ve fonksiyonumuzda bu şekilde ekledikten sonra fonksiyonumuzun bu çizgileri döndürmesini sağladık.

cizgileri_ciz() fonksiyonuna, çizgileri çizeceği yüzeyi belirtmek için ekran parametresiyle; sabit_cizgi_ekle() fonksiyonundan dönen Segment nesnelerini grafik olarak çizdirmek için de cizgiler parametresini ekledik. Çizgileri bir for döngüsü yardımıyla tek tek pygame.draw.line() ile ekrana çizdirilmesini sağladık. pv1 ile pv2 de çizgilerin Space deki pozisyonlarını ayarladık. rotated(body.angle) da ise çizgilerin bir açısı varsa ona göre bir düzenleme yapılması sağlanıyor. Eğer bir çizgi 45 derece aksi yöne yatıksa Vektörde o kısımın değeri artış ya da azalış gösterecektir.

p1 ve p2 de ise önceki dersimizde pygame’e özgü koordinat çevirme işlemi yapılıyor. Bu çevrimi yapılmış koordinatlar çizginin simülasyondaki yerine göre çizilmesini sağlıyor.

#-*- coding: utf-8 -*-
import sys
import pygame
from pygame.color import *
import pymunk

#def top_ekle(space):
#def top_cizdir(ekran, top):
# Yer kaplamaması için bu şekilde gösterildi. Siz kodunuzu olduğu gibi bırakın.

def sabit_cizgi_ekle(space):
    govde = pymunk.Body(pymunk.inf, pymunk.inf)
    govde.position = (300,200)
    l1 = pymunk.Segment(govde, (-200, 0), (200.0, 0.0), 5.0)
    l2 = pymunk.Segment(govde, (-200.0, 0), (-200.0, 50.0), 5.0)
    l3 = pymunk.Segment(govde, (200.0, 0), (200.0, 50.0), 5.0)
    space.add_static(l1, l2,l3)
    return l1,l2,l3

def to_pygame(p):
    """pymunk-pygame koordinat düzenlemesi yapar."""
    return int(p.x), int(-p.y+600)

def cizgileri_ciz(ekran, cizgiler):
    for cizgi in cizgiler:
        body = cizgi.body
        pv1 = body.position + cizgi.a.rotated(body.angle)
        pv2 = body.position + cizgi.b.rotated(body.angle)
        print cizgi.a.rotated(1.0), cizgi.b.rotated(0.0)
        p1 = to_pygame(pv1)
        p2 = to_pygame(pv2)
        pygame.draw.line(ekran, THECOLORS["red"], p1, p2)

pygame.init()
ekran = pygame.display.set_mode((600, 600))
saat = pygame.time.Clock()

space = pymunk.Space()
space.gravity = (0.0, -900.0)

cizgiler = sabit_cizgi_ekle(space)
toplar = []

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
        if event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
            sys.exit()
        if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
            top_sekli = top_ekle(space)
            toplar.append(top_sekli)
            pass

    ekran.fill(THECOLORS["white"])
    for top in toplar:
        top_cizdir(ekran, top)
    cizgileri_ciz(ekran, cizgiler)
    space.step(1/60.0)
    pygame.display.flip()
    saat.tick(60)

Örnekteki kodda cizgiler değişkenine sabit çizgilerin listesini tutturduk ve oyun döngümüzde cizgileri_ciz() fonksiyonumuza bu değişkeni parametre olarak vererek çizgilerimizi ekrana çizilmesini sağladık. Şimdi bu kodu çalıştırdığınızda bir hata yapmadıysanız fare tıklamalarınızda tepsi gibi bir alana top doldurabilirsiniz.

Şimdi sabit duran bu çizgileri bir pervanenin kanadı gibi bir noktasından iğneleyelim. Bunun için sabit_cizgi_ekle() fonksiyonunun adını cizgi_ekle() olarak değiştiriyoruz ve

def cizgi_ekle(space):
    devir_govdesi = pymunk.Body()
    devir_govdesi.position = (300,200)
    govde = pymunk.Body(50, 10000)
    govde.position = (300,200)
    l1 = pymunk.Segment(govde, (-200, 0), (200.0, 0.0), 5.0)
    l2 = pymunk.Segment(govde, (-200.0, 0), (-200.0, 50.0), 5.0)
    devir_eklemi = pymunk.PinJoint(govde, devir_govdesi, (0,0), (0,0))
    space.add(l1, l2, govde, devir_eklemi)
    return l1,l2

bu şekilde bir kod ortaya çıkarıyoruz… İlk olarak devir_govdesi adında yeni bir Body nesnesi oluşturuyoruz ve diğer Body nesnemizle aynı pozisyona getiriyoruz. Çizgileri tutan gövdemiz artık sabit olmayacağı için 50 kütleli ve 10000 momente sahip oluyor. Sağ taraftaki l3 çizgisinide çıkarıyoruz.

devir_eklemi adında bir PinJoint nesnesi oluşturduk. Bunu bir çubuğun ortasına saplanmış iğne gibi düşünebilirsiniz. PinJoint sınıfının ilk iki parametresi a ve b noktaları olmak üzere koordinat verisi alır; diğer iki parametree farklı bir değer vermeyecekseniz yazmanıza gerek yoktur. Hakkında pek bilgim yok; onun için rasgele değerler vererek ne işe yaradığını çıkartabilirsiniz.

Space sınıfının add_static() methodu yerine de add() methodunu kullandığımıza dikkat edin…

Son olarak şu satırı

cizgiler = sabit_cizgi_ekle(space)

şu şekilde değiştiriyoruz:

cizgiler = cizgi_ekle(space)

Kodumuzu çalıştırıp fare sol tuşuyla top oluşturarak topun çizgilere temas etmesiyle çizgilerin pervane gibi döndüğünü göreceksiniz. Tabii ki; bunu bu şekilde bırakmayacağız. Pervane gibi dönmesini engelleyip kısıtlı olarak sağ-sol aşağı doğru eğilmesini sağlayacağız.

def cizgi_ekle(space):
    devir_govdesi = pymunk.Body()
    devir_govdesi.position = (300,200)
    sinirli_devir_govdesi = pymunk.Body()
    sinirli_devir_govdesi.position = (200,200)
    govde = pymunk.Body(50, 10000)
    govde.position = (300,200)
    l1 = pymunk.Segment(govde, (-200, 0), (200.0, 0.0), 5.0)
    l2 = pymunk.Segment(govde, (-200.0, 0), (-200.0, 50.0), 5.0)
    devir_eklemi = pymunk.PinJoint(govde, devir_govdesi, (0,0), (0,0))
    eklem_siniri = 25
    sinirli_devir_eklemi = pymunk.SlideJoint(govde, sinirli_devir_govdesi, (-100,0), (0,0), 0, eklem_siniri)
    space.add(l1, l2, govde, devir_eklemi, sinirli_devir_eklemi)
    return l1,l2

Fonksiyonumuz biraz daha gelişti… sinirli_devir_govdesi adında yeni bir Body nesnesi tanımladık ve 200×200 pozisyonuna ayarladık. sinirli_devir_eklemi adında ise SlideJoint nesnesi tanımladık. İlk iki parametre PinJoint sınıfındaki gibidir. Üç ve dördüncü parametrelerde PinJoint sınıfının son iki parametresiyle aynı işleve sahiptir. parametre adı anchor olduğundan en uygun anlamı çapa oluyor. Buna göre x koordinatı -100 olan yere çapa atılmış oluyor. Belgelendirme yeterli düzeyde olmadığından ancak bu kadarı çıktı malesef… Son parametre eklem_siniri ise çizginin ne kadar kaydırılılabileceğini(?) söylüyor. Buna da farklı değerler vererek pekiştirme yapabilirsiniz. Son olarakta Space nesnemizin add() methoduna SlideJoint nesnemizi ekliyoruz. Fonksiyonla işimiz burada bitiyor…

Önceki derste listeye eklenen topların ekranda olmamasına rağmen listede yer işgal ettiğini ve bunlarında programın ekrana çizmeye çalıştığını söylemiştik. Ekleyeceğimiz tek satır kod ile y koordinatı sıfırın altına düşen topları listeden çıkartacağız ve olası şişme ve performans sorununun önüne geçeceğiz.

for top in toplar:
    top_cizdir(ekran, top)

Oyun döngümüzdeki bu for döngüsüne

if top.body.position.y < 0: toplar.remove(top)

kodunu ekleyerek

for top in toplar:
    if top.body.position.y < 0: toplar.remove(top)
    top_cizdir(ekran, top)

Bu şekle getiriyoruz. Artık kodumuz sağlıklı bir şekilde çalışmalı. Kodumuzun son hali şu şekilde:

#-*- coding: utf-8 -*-
import sys
import pygame
from pygame.color import *
import pymunk

def top_ekle(space):
    kutle = 1
    yaricap = 24
    eylemsizlik = pymunk.moment_for_circle(kutle, 0, yaricap)
    govde = pymunk.Body(kutle, eylemsizlik)
    pos = pygame.mouse.get_pos()
    govde.position = pos[0], 600-pos[1]
    sekil = pymunk.Circle(govde, yaricap)
    space.add(govde, sekil)
    return sekil

def top_cizdir(ekran, top):
    p = int(top.body.position.x), 600-int(top.body.position.y)
    pygame.draw.circle(ekran, THECOLORS["blue"], p, int(top.radius), 0)

def cizgi_ekle(space):
    devir_govdesi = pymunk.Body()
    devir_govdesi.position = (300,200)
    sinirli_devir_govdesi = pymunk.Body()
    sinirli_devir_govdesi.position = (200,200)
    govde = pymunk.Body(50, 10000)
    govde.position = (300,200)
    l1 = pymunk.Segment(govde, (-200, 0), (200.0, 0.0), 5.0)
    l2 = pymunk.Segment(govde, (-200.0, 0), (-200.0, 50.0), 5.0)
    devir_eklemi = pymunk.PinJoint(govde, devir_govdesi, (0,0), (0,0))
    eklem_siniri = 25
    sinirli_devir_eklemi = pymunk.SlideJoint(govde, sinirli_devir_govdesi, (-100,0), (0,0), 0, eklem_siniri)
    space.add(l1, l2, govde, devir_eklemi, sinirli_devir_eklemi)
    return l1,l2

def to_pygame(p):
    return int(p.x), int(-p.y+600)

def cizgileri_ciz(ekran, cizgiler):
    for cizgi in cizgiler:
        body = cizgi.body
        pv1 = body.position + cizgi.a.rotated(body.angle)
        pv2 = body.position + cizgi.b.rotated(body.angle)
        p1 = to_pygame(pv1)
        p2 = to_pygame(pv2)
        pygame.draw.line(ekran, THECOLORS["red"], p1, p2)

pygame.init()
ekran = pygame.display.set_mode((600, 600))
saat = pygame.time.Clock()

space = pymunk.Space()
space.gravity = (0.0, -900.0)

cizgiler = cizgi_ekle(space)
toplar = []

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
        if event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
            sys.exit()
        if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
            top_sekli = top_ekle(space)
            toplar.append(top_sekli)
            pass

    ekran.fill(THECOLORS["white"])
    for top in toplar:
        if top.body.position.y < 0: toplar.remove(top)
        top_cizdir(ekran, top)
    cizgileri_ciz(ekran, cizgiler)

    space.step(1/60.0)
    pygame.display.flip()
    saat.tick(60)

Ne yazık ki pymunk hakkında pek fazla belge yok ve Kaynak altında verdiğim linkler ne kadar yeterli olur bilemiyorum, ama İngilizcesi yeterli olanlar sınıf isimlerinden vs. öğrenmekte zorluk çekmeye bilirler. Bende bu yazıyı yazarken bu modülü öğrendiğim için sorularınıza cevap veremezsem kusuruma bakmayın...

Kaynak:

http://code.google.com/p/pymunk/wiki/SlideAndPinJointsExample

http://pymunk.googlecode.com/svn/trunk/docs/api/index.html

Bu yazı Creative Commons-BY-SA ile lisanslanmıştır. Bu yazıyı ilk sahibini belirtmek ve aynı lisansla dağıtmak koşuluyla kullanabilirsiniz.

Benzer Yazılar:

  1. pymunk 2B Fizik Kütüphanesi – Bölüm 1
  2. Pygame ile Oyun Programlama – Sprite 1. Bölüm
26
Kas

pymunk kullanımı basit 2 boyutlu oyunlar için hazırlanmış 2B fizik motorudur. Bu modül chipmunk üzerine inşa edilmiştir. pymunk’u pygame, pyglet, PySFML gibi oyun kütüphaneleriyle kullanabileceğiniz gibi PyQt gibi grafik arayüz kütüphaneleriyle de kullanabilirsiniz.

pymunk modülünü öğrenirken pygame modülünden faydalanacağız…

pymunk ile daire, dikdörtgen ve çokgen şekilleri fizik kurallarına uydurabileceğimiz sınıflar ile eklem oluşturmak, engel oluşturmak gibi işlemler için de sınıflar mevcuttur.

pymunk modülünü; GNU/Linux kullanıcıları python-setuptools paketini depolarından kurduktan sonra “easy_install pymunk” ya da “easy_install pip” dedikten sonra “pip install pymunk” komutunu vererek kurabilir, Windows kullanıcıları ise buradan uygun buldukları setup dosyasını indirerek kurabilirler. Tabii GNU/Linux kullanıcıları komutları verirken yönetici yetkisi almalıdır. Yani komutunuzun başına “sudo” komutunu eklemelisiniz…

Kurulum tamamlandıktan sonra Python yorumlayıcısına

import pymunk

yazarak test edebilirsiniz. Eğer ImportError hatası almıyorsanız sorun yok demektir. O zaman motoru çalıştıralım :)

pymunk’ta fizik kurallarını uygulayacağımız bir alan oluşturmamız gereklidir. Bu işi Space() sınıfı ile yapıyoruz. Daha sonra gravity özelliği ile yer çekiminin uygulanacağı yönü belirliyoruz…

import sys
import pygame
from pygame.color import *
import pymunk

pygame.init()
ekran = pygame.display.set_mode((600, 600))
saat = pygame.time.Clock()

space = pymunk.Space()
space.gravity = (0.0, -900.0)

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
        if event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
            sys.exit()

    ekran.fill(THECOLORS["white"])
    space.step(1/60.0)
    pygame.display.flip()
    saat.tick(60)

Örnekte görüldüğü gibi space değişkenine Space sınıfımızı atadık ve gravity özelliğine (0.0, -900.0) olarak atadık. İster bu şekilde yazalım, ister pymunk.Vec2d(0.0, -900.0) yazalım fark etmez. Sınıfımız doğru şekilde girilen veriyi kendisi Vec2d vektör nesnesine dönüştürecektir.

gravity özelliğine girilen ilk değer X koordinatını, ikincisi ise Y koordinatını temsil eder. Artı değer verilirse X için sağa, Y için yukarı doğru yer çekimi oluşur. Eksi değer girilirse tersi yönlere yer çekimi oluşur. Tabii yer çekimine maruz kalan nesnelerin vektörel değer girdiğimizden pygame koordinat tarzını ona göre ayarlamak gerekir.

Oyun döngümüzde 60 fps olarak ayarladığımız döngü sayısını fizik hesaplama süresiyle eşit tutuyoruz. step() methoduna girdiğimiz değerde oyun döngüsüyle eşit hesaplama yapmasını sağlıyor. Burada amaç simülasyonun uyumlu olmasını sağlamaktır.

Alanımızı oluşturduğumuza göre şimdi geometrik şekilleri çizdirmeye çalışabiliriz…

İlk olarak fare imleciyle ekrana tıkladığımızda bir daire çizdirelim ve fizik kurallarına göre yer çekimiyle aşağı doğru hareket etmesini sağlayalım…

def top_ekle(space):
    kutle = 1
    yaricap = 24
    eylemsizlik = pymunk.moment_for_circle(kutle, 0, yaricap)
    govde = pymunk.Body(kutle, eylemsizlik)
    pos = pygame.mouse.get_pos()
    govde.position = pos[0], 600-pos[1]
    sekil = pymunk.Circle(govde, yaricap)
    space.add(govde, sekil)
    return sekil

def top_cizdir(ekran, top):
    p = int(top.body.position.x), 600-int(top.body.position.y)
    pygame.draw.circle(ekran, THECOLORS["blue"], p, int(top.radius), 0)

top_ekle ve top_cizdir adında iki fonksiyon yazdık. top_ekle fonksiyonundan başlayalım:

Çizdireceğimiz şekle göre bir moment hesabı yapılması gerekiyor. Daire çizdireceğimiz zaman moment_for_circle fonksiyonunu dairenin moment hesabını yapmak için kullanırız. Değişken adlarından anlayacağınız gibi ilk parametresine kütle değerini, üçüncü parametresine de dairenin yarıçapını giriyoruz. 0 olan ikinci parametre ise dairenin iç yarıçapını temsil ediyor. Yani delikli para gibi bir şey düşünüyorsanız ikinci parametreye yarıçap verebilirsiniz.

Oluşturacağımız şekiller Body adında bir gövdeye ait olmalıdırlar. Body nesnemizi oluştururken şeklimizin momentinden ve kütlesinden haberdar olmasını sağlıyoruz. Sonra da çizileceği an gelince fare imleci pozisyonuna göre, ama y ekseni ekran yüksekliğinden çıkartılarak çizilmesi sağlanıyor. Çünkü matematikten hatırlarsanız y ekseni aşağı doğru eksilere inerken pygame de aşağı doğru artar. Bunu tersine çevirmek için böyle bir şey yapıyoruz.

Body nesnemiz ve yarıçap bilgisiyle bir Circle nesnesi oluşturuyoruz ve space parametresinden yararlanarak Space nesnemize gövdemizi ve şeklimizi ekliyoruz. Fonksiyonumuz bize Circle nesnemizi döndürüyor…

top_cizdir fonksiyonumuza ise ekran ve top parametrelerini almasını sağlıyoruz. p değişkeninde pygame’in anlayacağı koordinat verisini ayarlıyoruz ve draw.circle() fonksiyonumuz ile ekrana mavi renkli ve çapı 48 pixel olan bir daire çizilmesini sağlıyoruz.

Şimdi de ana kodumuza ufak eklemeler yaparak tam kodu yazalım.

import sys
import pygame
from pygame.color import *
import pymunk

def top_ekle(space):
    kutle = 1
    yaricap = 24
    eylemsizlik = pymunk.moment_for_circle(kutle, 0, yaricap)
    govde = pymunk.Body(kutle, eylemsizlik)
    pos = pygame.mouse.get_pos()
    govde.position = pos[0], 600-pos[1]
    sekil = pymunk.Circle(govde, yaricap)
    space.add(govde, sekil)
    return sekil

def top_cizdir(ekran, top):
    p = int(top.body.position.x), 600-int(top.body.position.y)
    pygame.draw.circle(ekran, THECOLORS["blue"], p, int(top.radius), 0)

pygame.init()
ekran = pygame.display.set_mode((600, 600))
saat = pygame.time.Clock()

space = pymunk.Space()
space.gravity = (0.0, -900.0)

toplar = []

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
        if event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
            sys.exit()
        if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
            top_sekli = top_ekle(space)
            toplar.append(top_sekli)

    ekran.fill(THECOLORS["white"])
    for top in toplar:
        top_cizdir(ekran, top)
    space.step(1/60.0)
    pygame.display.flip()
    saat.tick(60)

Evet toplar adında boş bir liste oluşturduk ve ekranda fare sol tuşuyla bastığımızda şeklimizin oluşmasını ve toplar listesine eklenmesini sağladık. Oyun döngümüzde ise listeye eklenen her topun sırayla çizilmesini sağladık. Kodu çalıştırıp topları sol fare tuşuyla oluşturmaya başladıktan sonra subliminal mesaj gibi mavi topların belirip kaybolduğunu görebilirsiniz. Bu durum ya modüllerden kaynaklanan bir durum ya da listeye eklenen ama ekrandan çıkmış toplarında çizilmeye çalışmasından kaynaklı olabilir. Bir sonraki devam dersimizde bu konuyuda halletmeye çalışacağız…

Bu yazı Creative Commons-BY-SA ile lisanslanmıştır. Bu yazıyı ilk sahibini belirtmek ve aynı lisansla dağıtmak koşuluyla kullanabilirsiniz.

Benzer Yazılar:

  1. Pygame ile Oyun Programlama – Sprite 1. Bölüm
  2. Pygame ile Oyun Programlama – Sprite 2. Bölüm
  3. Pygame ile Oyun Programlama – Sprite 3. Bölüm
23
Kas

Xml verilerini işlemek için çeşitli yapılar vardır(dom, sax gibi). Bu derste ağaç yapısını kullanan ElementTree modülünü öğreneceğiz ve hız ve performans bakımından C ile yazılmışı olan cElementTree modülünü kullanacağız.

Bu modül xml.etree modül paketinin bir parçasıdır. Modülümüzü farklı şekillerde çağırabiliriz.

from xml.etree import cElementTree
import xml.etree.cElementTree as cElementTree

Öncelikle xml etiketi oluşturmayı ve bu etiketlere nitelik ve değer atamasını öğrenelim.

from xml.etree import cElementTree

root = cElementTree.Element("diller")

child = cElementTree.SubElement(root, "dil")
child.text = "Python"

child = cElementTree.SubElement(root, "dil")
child.text = "Ruby"


Element methoduyla root etiketimizi “diller” adıyla oluşturduk. Çocuk etiket olarak SubElement methodundan faydalandık ve ilk parametresine root değişkenini yazarak ebeveyn etiketini belirledik ve çocuk etiketimizin adını “dil” olarak belirledik. SubElement’in text niteliğini kullanarak etiketimizin değerini “Python” ve sonraki tanımlamamızda “Ruby” olarak girdik.

cElementTree.dump(root)

koduyla xml çıktısı alabiliriz.

<diller><dil>Python</dil><dil>Ruby</dil></diller>

Eğer etiketlerimize nitelikte eklemek istersek Element methoduna ikinci, SubElement methoduna üçüncü bir parametreyi sözlük tipinde veri girerek ekleyebiliriz.

from xml.etree import cElementTree

root = cElementTree.Element("diller", {"type":"script"})

child = cElementTree.SubElement(root, "dil", {"version":"3.2"})
child.text = "Python"

child = cElementTree.SubElement(root, "dil")
child.text = "Ruby"

cElementTree.dump(root)
<diller type="script"><dil version="3.2">Python</dil><dil>Ruby</dil></diller>

Methodlara parametre olarak girmek yerine methodların attrib niteliğine sözlük verisini girebileceğiniz gibi set() methoduyla da nitelik ekleyebilirsiniz.

child.attrib = {"version":"3.2"}
child.set("version", "3.2")
[python]

Bir etiketin niteliğinin taşıdığı veriye ihtiyaç duyarsanız;

[python]
child.get("version")

gibi bir kod ile veriye ulaşabilirsiniz.

cElementTree.dump() sys.stdout ile yazdırır. Bir değer döndürmez. Bunun için cElementTree.tostring() fonksiyonunu kullanmalısınız.

Eğer etiketteki tüm nitelik ve değerlerine ulaşmak isterseniz items() sadece nitelik adına ulaşmak isterseniz de keys() methodunu kullanabilirsiniz.

print child.items()

[("version", "3.2")]

print child.keys()

["version"]

SubElement kullanmak istemiyorsanız, oluşturduğunuz çocuk Element nesnelerini ebeveyn Element nesnesinin append() methodu ile birer birer, ya da extend() methoduna liste olarak gireceğiniz Element nesneleriyle toplu olarak ekleyebilirsiniz.

Ekleyeceğiniz Element’in sırasını belirlemek isterseniz de insert() methodunu kullanabilirsiniz

root.insert(0, child)

Bu kod ile root’a eklenen child ilk sıraya eklenmiş olacaktır.

Kendinize göre bir xml verisi hazırladınız ve bir etiketin çocuğu olan etiketlerin bir listesini almak istediniz. Bunu getchildren() methodu ile alabilirsiniz. Eğer bir etiketin çocuk etiketi varsa Element nesnelerinden oluşan bir liste dönecektir; aksi halde boş bir liste döner. Eğer o çocuk etiketlerinde çocuk etiketi varsa ayrıca o Element nesnelerininde getchildren() methodunu çağırmalısınız.

Silmek istediğiniz bir SubElement nesnesi var ise Element nesnenizin remove() methoduna SubElementi girmelisiniz.

Öğreneceğimiz bir kaç methodu ise örnekle anlatalım ve bunu yaparken de başka şeylerde öğrenelim…

Örneğin elimizde bir xml dosyası var ya da internetten bir xml verisi çekeceğiz. Dışarıdan alınan xml verisini nasıl parse edeceğimizi ve Element’in kalan methodlarını da öğrenelim.

Elimizde şöyle bir xml verisi olduğunu varsayarak kodumuzu yazalım;

<urlset>
    <url>
        <loc>http://www.metehan.us/</loc>
        <lastmod>2011-11-20T19:43:57+00:00</lastmod>
        <changefreq>daily</changefreq>
        <priority>1.0</priority>
    </url>
    <url>
        <loc>http://www.metehan.us/parcala-buyuk-boyutlu-dosyalari-boler-birlestirir-ve-kontrol-eder.html</loc>
        <lastmod>2011-11-20T19:43:57+00:00</lastmod>
        <changefreq>daily</changefreq>
        <priority>0.8</priority>
    </url>
    <url>
        <loc>http://www.metehan.us/python-kurulum-betigi-hazirlamak.html</loc>
        <lastmod>2011-10-16T22:07:54+00:00</lastmod>
        <changefreq>daily</changefreq>
        <priority>0.8</priority>
    </url>
    <url>
        <loc>http://www.metehan.us/qlineedit-ile-otomatik-ve-sekme-iletamamlama.html</loc>
        <lastmod>2011-09-23T18:42:40+00:00</lastmod>
        <changefreq>daily</changefreq>
        <priority>0.8</priority>
    </url>
    <url>
        <loc>http://www.metehan.us/qsettings-sinifi-kullanimi.html</loc>
        <lastmod>2011-09-14T11:59:34+00:00</lastmod>
        <changefreq>daily</changefreq>
        <priority>0.8</priority>
    </url>
</urlset>

bu veriyi ayrıştıracağız ve düzenli bir şekilde çıktısını alacağız…

#-*- coding: utf-8 -*-
from xml.etree import cElementTree

xmlVerisi = open("sitemap.xml").read()
xmlParse = cElementTree.XML(xmlVerisi)
urlTagList = xmlParse.findall("url")

for urlTag in urlTagList:
    print "URL: %s"%urlTag.find("loc").text
    print "Tarih: %s"%urlTag.find("lastmod").text
    print "Değişme Zamanı: %s"%urlTag.find("changefreq").text
    print "Öncelik: %s"%urlTag.find("priority").text
    print "--------------------------------\n"

Örnek kodumuz bu… sitemap.xml dosyasını okuyup XML() fonksiyonuna parametre olarak xml verisini girdik ve parse işlemini gerçekleştirmiş olduk. Bu fonksiyon geriye bir Element nesnesi döndürür. Bu Element nesnesi root etiketi taşır; yani örnek verimizse “urlset” etiketi. Xml verisindeki url etiketine sahip olanlar findall() methoduyla liste olarak aldık ve bir for döngüsü oluşturduk. Bu döngüde url etiketinin çocuğu olan loc, lastmod, changefreq ve priority etiketlerini find() methodu ile taşıdığı veriyi aldık. Örnekten de anlaşılacağı gibi find() methodu tek bir sonuç döndürüyor(aynı etiketten fazla olsa da ilk sıradakini alır).

Son olarak ise bu modülle oluşturulan xml verilerinin çıktısı okunabilir olmuyor. Okunabilirlik için Kaynak‘tan ikinci bağlantıyı inceleyebilirsiniz.

Kaynak: The ElementTree XML API
ElementTree ile XML oluşturmaya giriş

Bu yazı Creative Commons-BY-SA ile lisanslanmıştır. Bu yazıyı ilk sahibini belirtmek ve aynı lisansla dağıtmak koşuluyla kullanabilirsiniz.

Benzer yazı yok.

16
Eki

Python ile ilginenler, en azından bir kaç kez üçüncü şahısların yazdığı modüllerden yüklemiştir ve bu modülü yüklerken modülle birlikte gelen setup.py betiğini build ve/veya install parametresiyle çalıştırmıştır. Bu kurulum betiği sayesinde geliştiriciler zaman kaybetmeden modülü kullanılabilir hale getirir… Biz de bu yazıda işimizi yeteri kadar görecek şekilde kurulum betiği dosyası hazırlamayı öğreneceğiz. Bu yazıdan kısa süre önce ilk defa kurulum betiği hazırlamış oldum…

Zorunlu olmasa da genel olarak kurulum betiğine setup.py adını veriyoruz ve bu yazı da kurulum betiğimizi bu dosyada hazırlayacağız.

Bir kurulum betiği hazırlamak için Python ile gelen distutils modülünü kullanıyoruz.

from distutils.core import setup

setup()

distutils.core modülünde bulunan setup fonksiyonunu kullanarak modülümüzle ilgili gerekli bilgileri girmemiz gerekiyor.

Örneğin hede.py adında tek dosyadan oluşan bir modülümüz var. Bunun kurulum betiğini oluşturalım…

from distutils.core import setup

setup(
    name = "hede",
    py_modules = ["hede"],
    version = "1.0",
  • name parametresi uygulamanın adını belirtir.
  • py_modules parametresine liste olarak girilen isimler *.py dosyalarının uzantısız hali olmalıdır. Bu parametre tekil modülleri bekler.
  • version parametresi ise uygulamanızın versiyonunu belirtir.

name ve version parametreleri, uygulamanızı easy_install ve/veya pip ile kurulabilmesi için pypi.python.org/pypi adresinde yayınlamanızda gereklidir. Şimdi setup.py dosyasının olduğu dizine konsol ile girin ve;

python setup.py sdist

komutunu verin. Bulunduğunuz dizinde dist adında bir dizin ve içinde hede-1.0.tar.gz adlı bir dosya oluşacaktır. Daha sonra bu dosyayı pypi.python.org/pypi adresinde nasıl yayınlayacağımızı göreceğiz…

hede.py modülünü kurmak için de;

python setup.py install

komutunu verebilirsiniz. Windows kullanıcıları için binary dosya oluşturmak için;

python setup.py bdist_wininst

Fedora, Mageia gibi rpm paket sistemini kullanan kişiler için;

python setup.py bdist_rpm

komutunu verebilirsiniz. Windows kullanıcıları için Linux altında da binary(*.exe) oluşturmak mümkün. Ancak bunun için Python’un geliştiriciler için olan paketini kurmanız gerekmektedir. Ubuntu da python-dev ismiyle bulup kurmak mümkün. Diğer GNU/Linux dağıtımlarında da ismi büyük ihtimal aynıdır…

Aynı şekilde rpm paketi oluşturmak içinde python-dev paketinin kurulu olması gerekebilir…

Uygulamamızı biraz daha geliştirelim. lib adında bir modül paketi oluşturup(İçinde __init__.py olan bir dizin) içine hedelib.py ve hodolib.py modüllerini ve lib2 adında bir modül paketi oluşturup içine hedelib2.py adlı bir modül oluşturduğumuzu varsayalım.

hede.py
lib/
    lib2/
        __init__.py
        hedelib2.py
    __init__.py
    hedelib.py
    hodolib.py

Uygulamamızda modül paketi varsa setup() fonksiyonuna packages parametresini ekleyip paketlerin ismini içeren bir liste girmeliyiz.

from distutils.core import setup

setup(name='hede',
      version='1.0',
      description='Python hede kütüphanesi',
      author='Metehan Özbek',
      author_email='metehan [at] metehan.us',
      url='http://www.metehan.us',
      packages=['lib', 'lib.lib2'],
     )

Python paket indeksinde gözükmesi içinde url, author, author_email ve description parametrelerini girdik.

python setup.py install

Komutunu verdiğinizde Python’un kütüphanelerinin bulunduğu dizin içerisindeki site-packages(Ubuntu da dist-packages) dizininde; hede.py ve lib modül paketi içinde, lib2 dizini ve modüllerle beraber yüklenecektir. Bu durumda Python yorumlayıcısında modülünüzü şu şekilde çağırabilirsiniz:

import hede
from lib.lib2 import hedelib2
from lib import hedelib, hodolib

Tabii lib ismi çok kullanıldığından bir ihtimal çakışma olabilir. Bunu önlemek için ana modül paketinizi hede yapmanız daha doğru olacaktır.

from hede import hede
from hede.lib.lib2 import hedelib2

Uygulamanızda çalıştırılabilir bir betik oluşturmak isteyebilirsiniz. Oluşturduğunuz betiği(ör: hede) konsoldan hede yazarak çalıştırmak isteyebilirsiniz. setup() fonksiyonuna gireceğiniz scripts parametresiyle liste olarak girdiğiniz betikleri GNU/Linux ortamında /usr/bin/ altına Windowsta ise Python’un kurulduğu dizin içerisindeki Scripts dizinine yazdırabilirsiniz. Yalnız Windowsta betiğinizi çalıştırabilmek için bir *.bat dosyası ile betiğinizi çalıştırmanız gerekmektedir(ör: hede için hede.bat) ve path e ekli olmadığından cmd ile betiğinizi çalıştıramazsınız.

hede.py
script/
    hede
lib/
    lib2/
        __init__.py
        hedelib2.py
    __init__.py
    hedelib.py
    hodolib.py
from distutils.core import setup

setup(name='hede',
      version='1.0',
      description='Python hede kütüphanesi',
      author='Metehan Özbek',
      author_email='metehan [at] metehan.us',
      url='http://www.metehan.us',
      packages=['lib', 'lib.lib2'],
      scripts=["script/hede"]
     )

Uygulamız gelişti ve resim, ses dosyası gibi veriler ekledik. Dizin içindeki verileri almak için data_files, modül paketi içindeki veri dizinlerini almak için package_data parametrelerini kullanırız. Yeni dizin-dosya yapımız şöyle olsun:

hede.py
data/
    veri.db
script/
    hede
lib/
    lib2/
        data/
            simge.png
        __init__.py
        hedelib2.py
    __init__.py
    hedelib.py
    hodolib.py

Bu dosya-dizin yapısına göre veri dosyalarımızı kurulum betiğimize ekleyelim.

from distutils.core import setup

setup(name='hede',
      version='1.0',
      description='Python hede kütüphanesi',
      author='Metehan Özbek',
      author_email='metehan [at] metehan.us',
      url='http://www.metehan.us',
      packages=['lib', 'lib.lib2'],
      scripts=["script/hede"],
      data_files=[("data", ["veri.db"])],
      package_data={"lib.lib2":["data/*"]}
     )

Görüldüğü üzere data_files bir liste verisi alıyor. Listenin her elemanı birer tuple. Tuple ilk elemanı dizin, ikinci elemanı ise dosya ismidir. package_data ise bir sözlük veri tipi alıyor ve her elemanın anahtar ögesi modül paketi ismi, değer ögesi ise liste olarak dizin ve dosya alıyor. Burada düzenli ifadelerin kullanımıda mümkün(regex).

setup.py betiğini çalıştırırken kullandığımız sdist argümanıyla uygulamanızın sıkıştırılmış halini alıyorsunuz. Bu dosya içerisinde bulunmasını istediğiniz ek dosyaları MANIFEST.in adlı dosya da tanımlayabilirsiniz. Buradan kullanılabilir kodları öğrenebilirsiniz.

setup() fonksiyonunun alabileceği tüm parametrelere buradan ulaşabilirsiniz. Temel olarak bir kurulum betiğini hazırlamayı öğrendiğimize göre artık modülümüzü-uygulamamızı Python Package Index sayfasına yollayalım…

setup.py betiğimizin bulunduğu dizine konsol ve/veya cmd ile geliyoruz ve

python setup.py register

diyoruz. Bizden dört adet seçenekten birini seçmemizi istiyor.

running register
running check
We need to know who you are, so please choose either:
 1. use your existing login,
 2. register as a new user,
 3. have the server generate a new password for you (and email it to you), or
 4. quit
Your selection [default 1]:

Daha önce pypi ye üye olmadıysanız 2 yazıp kayıt işlemini gerçekleştirebilirsiniz. Ben önceden kayıt olduğum için 1 yazıp devam ediyorum…

İkinci aşamada kullanıcı adı ve şifremizi soruyor ve sırayla gerekli bilgileri giriyoruz. Ardından kullanıcı bilgilerimizi kayıt edeyim mi diye soruyor. Yanıtı y diye verirseniz uygulamanızı güncelleyip yollamak istediğinizde kullanıcı adı ve şifre girmekten muaf olursunuz.

Username: mthnzbk
Password:
Registering parcala to http://pypi.python.org/pypi
Server response (200): OK
I can store your PyPI login so future submissions will be faster.
(the login will be stored in /home/metehan/.pypirc)
Save your login (y/N)?y

Buraya kadar sadece uygulamamızı pypi sayfasına kayıt ettirmiş olduk. Şimdi ise uygulamamızı arşivleyip ya da çalıştırılabilir hale getirip uygulama sayfasında yayınlayalım.

python setup.py sdist upload

ya da

python setup.py bdist_wininst upload
python setup.py bdist_rpm upload

Bir aksilik olmazsa uygulamanız, uygulama sayfanızda gözükmek üzere yüklenecektir…

Kaynaklar:
http://docs.python.org/distutils/setupscript.html
http://docs.python.org/install/index.html
http://docs.python.org/distutils/apiref.html

Buraya bakarlar:
http://docs.python.org/distutils/configfile.html
http://docs.python.org/distutils/sourcedist.html
http://docs.python.org/distutils/builtdist.html
http://pypi.python.org/pypi?:action=list_classifiers

Bu yazı Creative Commons-BY-SA ile lisanslanmıştır. Bu yazıyı ilk sahibini belirtmek ve aynı lisansla dağıtmak koşuluyla kullanabilirsiniz.

Benzer Yazılar:

  1. Python da Kaynak Kodları Gizlemek
  2. Python Kodlarını Derlemek
15
Ağu

Bu yazıda cx_Freeze modülünü kullanarak Python kodlarımızı nasıl çalıştırılabilir(*.exe, Linuxta uzantı yok) yapacağımızı öğreneceğiz. Bu sayede yazılımlarınızı fazladan Python kurulumu yaptırtmadan dağıtabileceksiniz. Ayrıca ortaya çıkan ürün portable uygulama olarakta kullanılabilir…

Öncelikle GNU/Linux kullanıcıları için bu işin nasıl yapılacağını anlatacağım…

Kullandığınız GNU/Linux dağıtımızın paket depolarında mevcut olması muhtemel bu modülü paket yöneticinizden cx_freeze olarak aratıp kurabilirsiniz(Pardusta adı python-cx_freeze, Ubuntu da cx-freeze).

Derlemek istediğiniz Python projenizin bulunduğu dizine girin ve bir konsol açın. Konsola “cxfreeze dosya_adi.py” komutunu verin. cxfreeze betiği kodlarınızı inceleyip gerekli modülleri tespit eder ve çalıştırılabilir bir dosya oluşturur. Bunu aynı dizinde dist adlı dizinde görebilirsiniz. Eğer projenizle ilgili resim, müzik veya ayar dosyalarınız varsa dağıtacağınız uygulamanıza bu dosyaları ilave edin…

Şimdi ise Windows kullanıcıları için nasıl kod derleneceğine gelelim… Windows kullanıcıları cx_Freeze modülünün Python sürümüne göre olan binary dosyasını indirip kurmaları gerekmektedir.

İşimizi kolaylaştırmak için Gui2exe adlı uygulamayı kullanacağız. Bu sayede görsel olarak setup.py dosyası hazırlayacağız. Gui2exe uygulamasını buradan indirebilirsiniz. Bu uygulama wx adlı gui modülü gerektirdiği için wxPython sitesinden Python sürümünüze göre olanın unicode destekli olanını indirip kurun. Artık Gui2exe uygulamasını çalıştırabiliriz.

Gui2exe yi arşivden çıkarıp GUI2Exe adlı klasöre giriyoruz ve GUI2Exe.py dosyasına çift tıklayıp uygulamayı çalıştırıyoruz…

Açılan ekranda File>New project… yoluna tıklayıp çıkan dialogda OK butonuna basıyoruz. Sol menüde bulunan My Projects in altındaki GUI2Exe Project e çift tıklıyoruz. Sağda açılan kısımdan cx_Freeze ye tıklıyoruz.

Uygulama ekranının ortasında GUI2Exe Project adında bir sekme oluştu. Bu sekmede yer alan grupların ne işe yaradıklarına bakalım…

Target Classes(1):

Exe Kind başlığının altındaki satıra tıklayarak uygulamanızın konsol mu, yoksa guili bir uygulama mı olduğunu seçiyorsunuz.

Python Main Script başlığının altındaki satırın sağ tarafına tıklayarak *.exe ye dönüştüreceğiniz betiğin yolunu giriyorsunuz.

Executable Name kısmına *.exe dosyanızın adını yazıyorsunuz.

Version kısmına uygulamanızın versiyonunu, Description kısmına ise uygulamanızın ne işe yaradığını açıklayan bir yazı yazıyorsunuz.

Author kısmına Uygulamayı geliştirenin adını, Program Name kısmına ise uygulamanızın adını yazıyorsunuz.

Common Options:

Optimize kısmından 0-2 arası bir değer vererek Python kodlarının optimizasyonunu ayarlayabilirsiniz.

Compressed kısmından oluşturulacak *.zip dosyalarının sıkıştırılmasını sağlayabilirsiniz.

Dist Directory kısmını aktif ederek binary dosyaların oluşacağı dizinin adını değiştirebilirsiniz.

Packages grubunda ise sağ alt taraftaki + butonuna tıklayarak Python paketi ekleyebilirsiniz. Örneğin, PyQt veya pygame kullanarak bir uygulama geliştirdiyseniz bu gruptaki liste widgetine bu paketin adını yazmalısınız ki derlemeden sonra çalıştırdığınızda hata almayasınız.

Other Options grubunda ki Icon File kısmından *.exe dosyanızın gözükeceği resmi seçebilirsiniz.

Her şey tamamsa ve bir hata olduğunu düşünmüyorsanız sağ altta bulunan Compile butonuna tıklayarak derleme işlemine başlayabilirsiniz. Derleme başarılı olursa bir dialog çıkacak ve çalıştırmak isteyip istemediğinizi soracak. Başarılı bir derlemeden sonra *.exe ye çevirdiğiniz betiğin bulunduğu dizine girip binary dosyalarınıza ulaşabilirsiniz.

İsterseniz File menüsünden Export setup file… a tıklayarak oluşan setup.py dosyasını kaydedebilirsiniz.

Gui2exe kullanırken Türkçe karakter kullanırsanız derlemede hata verecektir. Türkçe karakter kullanmakta ısrarlıysanız setup.py yi dışarı aktararak dosyanın başına #-*- coding:utf-8 -*- satırını eklemelisiniz.

Aynı setup.py dosyasını GNU/Linux altında da kullanabilirsiniz. Ancak Gui2exe Windows altında çalıştığı için, GNU/Linux da setup.py dosyasını elle oluşturmanız gerekecektir. İsteyenler buradan setup.py dosyasına neler yazılabileceğini öğrenebilirler.

Ek: setup.py dosyasını python setup.py build komutuyla kullanıp binary oluşturabilirsiniz.

Windows kullanıcıları cxfreeze betiğini kullanmak isterlerse, Python’un kurulu olduğu dizinde ki Script dizinine girerek cxfreeze.bat dosyasını kullanabilirler. Bunun için cmd ile o dizine girip cxfreeze.bat dosya_yolu\dosya_adi.py gibi bir komutla aynı GNU/Linuxta ki gibi derleyebilirler. Yalnız gui kullanılan bir uygulamayı derliyorsanız programı çalıştırdığınızda cmd de açılacaktır…

Derleme de sorun yaşayanlar sorunları bildirirse çözmeye çalışırız…

Yazım hatası varsa bildiriniz.
Bu yazı Creative Commons-BY-SA ile lisanslanmıştır. Bu yazıyı ilk sahibini belirtmek ve aynı lisansla dağıtmak koşuluyla kullanabilirsiniz.

Benzer Yazılar:

  1. Python da Kaynak Kodları Gizlemek