19
Oca

# service list
Traceback (most recent call last):
File “/bin/service”, line 330, in <module>
main(sys.argv[1:])
File “/bin/service”, line 302, in main
list_services(use_color)
File “/bin/service”, line 180, in list_services
services.append((service, getServiceInfo(service, bus), ))
File “/bin/service”, line 170, in getServiceInfo
return obj.info(dbus_interface=”tr.org.pardus.comar.System.Service”)
File “/usr/lib/python2.5/site-packages/dbus/proxies.py”, line 140, in __call__
**keywords)
File “/usr/lib/python2.5/site-packages/dbus/connection.py”, line 607, in call_blocking
message, timeout)
dbus.exceptions.DBusException: tr.org.pardus.comar.dbus.unknownmodel: Application interface doesn’t exist.


Eğer bir Pardus kullanıcısı iseniz ve yukarıdaki hata size bir yerden tanıdık gelmiyorsa, konsoldan yönetici haklarıyla service list komutunu verdiğinizde bu hatayla karşılaşıyorsanız veya aynı şekilde Tasma'dan Sistem Seçenekleri » Servis Yöneticisi'ne erişmek istediğinizde Tasma kendinden geçiyor, donuyor [http://imaj.at/45480] ise, çözümü burada.

Sorunun sebebi, sanırsam kdebase paketinin kaldırılması veya güncellenmesi sonucu ÇOMAR veritabanında bozulan bir satır. Çözümü ise, Bahadır Kandemir'in hazırladığı bir Python betiği. Python betiği konsoldan yönetici haklarıyla çalıştırdığımızda gerekli işlemler yapılıyor ve sorun çözülüyor.
16
Ara

Yeni ve artık son okul dönemi ile birlikte Lookremix projesinden ayrılmak zorunda kaldım. Bir startup içerisinde bulunmak oldukça eğitici oldu benim için. Hem bir sosyal medya aracının oluşturulurken ne gibi badireler atlattığını görmüş oldum. Hem de bir yazılım geliştirici olarak daha önce hiç el atmadığım meselelere el atmak durumunda kaldım. Bunun yanında venezuelalı kadınların nasıl çekilmez olabileceğini devamlı sizle nasıl dalga geçmeyi başarabileceğini öğrenmiş oldum :P. Benim için oldukça çetrefilli ama bir yandan da oldukça zevkli bir iş oldu. Keşke daha fazla devam edebilseydim diyorum ama belli olmaz belki ileride yollarımız tekrar kesişir.

Şu anda ise ilk göz ağrım bilsin'i tekrar ayağa kaldırmak için elime bir fırsat geçti. Geçerli sosyal medya araçlarının zayıflığı ve bilsin'in neden güçlü bir araç olacağı konusunda okuldaki jüriye yaptığım sunum oldukça ikna edici oldu ve şu bilsin resmi olarak bitirme projem haline dönüştü. Ancak çok çalışmam gerek çünkü şu anda her ne kadar kırık dökük de olsa çalışan bir alet (tool) görünümü verse de aslında kafamdaki ideolojiden ve sağlamlıktan uzak durumda.

Projeye daha önce başlarken yaptığım yanlış teknoloji seçimlerini ve kervan yolda düzülür diyip yolda yol değiştirmeleri (gerçekten çok fazla enerji ve kaybı oluyor) tekrar yaşamamak için mümkün olduğunca belgeli, planlı davranmaya çalışıyor. Çıkacak sorunları mümkün olduğunca ön görmeye çalışıyorum. Blog üzerinden çok fazla ayrıntı vermeyi uygun görmüyorum ama projenin %90'ının sağlam restFul api oluşturmaktan geçtiğini ve mümkün olduğunca akışkan bir yapıda olacağını söyleyebilirim. Tabi bu noktada Django kullanmak bir az saçma oluyor zira api yazmak için context processorlere ya da template sistemine ihtiyaç duymuyorum. Bunun yanında Django ile long pooling yapmak ya da websockets kullanmak deveyi at yarışına sokmak gibi bir şey olurdu.

Bu noktada Node.js gel beni kullan diye göz kırpıyor, diğer kolumda da Tornado var. Bunları kendimce karşılaştırmaya çalıştım ancak eğer yanlış bilgi verdiğimi, yanıldığımı düşünüyorsanız lütfen yorum bırakın.

Performans

Node.js Google beyin V8 adlı javascript motorunu kullanıyor. Javascript kodları derlenip makina diline çevriliyor. Bu da kallavi bir hız demek. Tornado ise bunu ta ki Python 3.3 çıkana kadar yapamayacak(mış). İzlediğim node.js sunumunda yapılan testte ki bu test sadece bir "hello world" testi. Node.js saniyede 4340 cevap verebilirken tornado ise sadece 2344 cevap verebilmiş. Sözün özü Node.js performans konusunda Tornado'yu ikiye katlıyor.

Dil Yapısı

Bu noktada Tornado golünü atıyor zira hiç bir programcının Python varken Javascript kullanmak isteyeceğini sanmıyorum. Javascript'in iğrenç bir syntax yapısı var. Bu Python sever birinin şahsi fikri olmakla beraber, pek çok kişinin de noktalı virgül ya da memeli parantezler ile boğuşmak isteyeceğini sanmıyorum. Hoş, syntax olayı CofeeScript sayesinde çözülebiliyor ancak yine de dahili standartlaşmış kütüphanelerin eksikliği hissediliyor. Bir each döngüsü yaratmak için bile harici bir kütüphaneye ihtiyaç duymak, bende huzursuzluğa yol açıyor. Yengeç burcu programcılar için önermiyorum. :)

İkinci olarak javascript ilk defa browser dışında bir mecrada iş görmeye başladığı için bir çok kütüphane olgunlaşmamış durumda. Halbu ki Python 1994 de 1.0 versiyonuna ulaştı yıllardır her konuda kütüphane geliştirilmekte kendisi için. Node.js nin şu anki versiyonu 0.4.1 Tornado'nun ise 2.1.1.

Üçüncü olarak, Javascript in doğal halinin etkinlik tabanlı (event-driven) bir dil olduğunu bu yüzden geliştirilen kütüphanelerin haliyle asenkron kütüphaneler olduğunu. Python ise aslında sıralı (satır satır) işlenen bir dil olması itibari ile Tornado ile kullanacağınız kütüphanelerin özel olarak asenkron olarak yazılmış kütüphaneler olması gerektiğini eklemem gerekiyor. Anlayacağınız Tornado içinde mysqllib'i direkt olarak import edip kullanamıyorsunuz. Bunun yerine asenkron çalışacak şekilde tasarlanmış mysql kütüphanesi ne ise onu bulup kullanmanız gerekiyor.

Ancak ilginçtir ki her ne kadar Tornado daha olgun olsa da içerisinde bir session management olayı bulundurmuyor. Bu bana çok garip geldi. Sanırım Django'da ki:

if user.is_authenticated():
...
...

Türevi sorular soramayacağımız manasına geliyor Tornado'ya. Belki authentication olayları başka türlü cookie tabanlı atraksiyonlarla (OAuth?) çözülüyordur bilemiyorum.

Topluluk

Node.js'in çok heyecanlı bir topluluk henüz bir velet olmasına rağmen inanılmaz ilgi görüyor. Aşağıdaki bu rakamlar söylediğimi kanıtlar nitelikte: (Fork, Takipçi ve İlgili Depo sayılarını Github'dan aldım)

Fork Takipçi İlgili Depo Eposta Listesi
Tornado 510 3,313 364 1779
Node.js 1,339 11,944 5842 6590

Sonuç

Sonuç olarak Node.js topluluk ve performans olarak Tornado'yu dövüyor gözüküyor. Ancak sanırım geliştiriciler arasında bir garip moda ya da trendin peşinden hızla gitme durumu var. Yeni bir teknoloji afili bir sunumla anlatılıp da bir kaç yerde yazılıp çizildiği zaman hurra herkes o tarafa gidiyor. Sonra herkes sakinleşiyor hangi dili rahat kullanıyorsa onu kullanmaya devam ediyor. Bu yüzden bu 7000 kişilik e-posta listelerini falan biraz şişirilmiş rakamlar olarak görüyorum. Ayrıca bu devasa kitleden kaç tanesi gerçek bir iş görebilmek üzere sizin ofisinize gelip çalışabilecek insanlardır bunu hesap etmek gerek. üç mü beş mi?

Bunun yanında Node.js teoride bu kadar ilgi görmesine rağmen, henüz kendisini savaş arenasında görmüş değiliz. Gerçek - büyük projelerde ne gibi problemler çıkaracağı konusunda pek fikrimiz yok. Tornado ise halihazırda Facebook'un ve FriendFeed'in ağır işlerini gören bir sistem.

Bütün bunlara dayanarak, üzülerek Node.js ye bizimle değilsin diyorum. Zira saniyede 4bin request karşılayabiliyor olması bende yarattığı rahatsızlık hissini gidermeye yetmiyor. Zaten bir gün sunucularım altından kalkamayacağım bir yükle karşılaşırsa zaten para kazanıyorum demektir bir sunucu daha koyarım.

Kaynaklar:

Çalıştığım projede iş takip sistemi olarak pivotaltracker kullanıyorduk. Daha sonra GitHub'a taşınma kararı aldık. Bu taşınma işlemini otomatik olarak gerçekleştirebilecek bir script bulamadım. Bende kendim yazmaya karar verdim. Size de birgün lazm olabilir. Buyrun kullanın.

Currently i needed to migrate from pivotaltracker to github. I could'nt find any automated solution for that. So i wrote my solution in Python. Use freely when you need it. :)

from github2.client import Github
from csv import reader as CsvReader

# FILL INFORMATION BELOW

# your username at github
GITHUB_USERNAME = ""

# your api token, you can find it at https://github.com/account/admin
GITHUB_API_TOKEN = ""

# path to file that you exported from pivotal tracker
PROJECT_CSV_PATH = ""

# project path at github like: "user/projectname"
GITHUB_PROJECT_PATH = ""

github = Github(
username=GITHUB_USERNAME,
api_token=GITHUB_API_TOKEN,
request_per_second=1)

reader = CsvReader(open(PROJECT_CSV_PATH, "r"), delimiter=",")

for row in reader:
print "title :", row[1]
print "description :", row[14]
print "--------"
github.issues.open(GITHUB_PROJECT_PATH, title=row[1], body=row[14])
7
Ara

İlk Django yazımda çevirimiçi ziyaretçilerin hesabını yapan bir uygulama yapımını anlatacağım. Bu dersten bir şey anlamak için Django hakkında biraz bilgi sahibi olmanız gerekecektir.

Türkçe kaynak için Google araması yaptığınızda karşınıza çıkacak kaynaklar büyük ihtimal şöyle olacaktır:

  • Django ile blog yapımı
  • Django belgelemelerindeki tutorialın aynısı, yani anket uygulaması

Ve başlangıç düzeyinde; internet üzerinde Türkçe olarak zaten yaygın olan başlangıç konuları… Benim anlatacağım konu da belki bu seviyede olacaktır, ama daha önce kafamın almadığı middleware konusunu azcık kavramış olmak ve bunu pratik olarak kullanmak olacak.

Öncelikle uygulamamızı deneyebilmek için bir proje oluşturmamız gerekiyor:

django-admin.py startproject sayacprojesi

Bu komutu konsolda veriyoruz ve projemizi oluşturuyoruz. Şimdi proje dizinine girip konsoldan şu komutu veriyoruz:

python manage.py startapp onlinecounter

Sayaç uygulamamızın temelini atmış olduk. Uygulamanın içine girelim ve çevirimiçi kullanıcıların veritabanında saklanması için gerekli olan model sınıfımızı models.py içine yazalım.

#-*- coding: utf-8 -*-
from django.db import models

class OnlineCounter(models.Model):
    ip = models.IPAddressField(verbose_name="IP Address", db_column="visitor_ip")
    is_user = models.BooleanField(verbose_name="User ?", db_column="is_user", default=False)
    visited_time = models.TimeField(verbose_name="Visited Time", db_column="visitor_time", auto_now_add=True)

    class Meta:
        db_table = "online_counter"
        verbose_name_plural = "Online Counter"

OnlineCounter adında bir Model sınıfı oluşturduk ve ip, is_user ve visited_time adında üç değişken tanımladık. Bunlardan ip değişkenine ip adresi kayıt edileceğinden “models” modülünün sağladığı IPAddressField sınıfını kullandık. Bu sınıf ip adresi için oluşturacağınız sütun için gerekli sql kodunu sağlar. Bu sütunun adının ise visitor_ip olarak gözükmesini sağlıyoruz.

is_user değişkenine ise BooleanField sınıfını kullandık. Siteyi ziyaret eden kişinin kayıtlı bir üye mi yoksa misafir mi olduğunu True ve False olarak veritabanında saklayacağız. BooleanField sınıfına db_column parametresiyle girdiğimiz “is_user” verisiylede sütun adını belirlemiş olduk. verbose_name parametresi Django yönetici panelinde verinin ne olduğu belirten bir ayrıntı olarak kullanılır.

Ziyaretçinin siteye girdiği anı belirlemek için de visited_time değişkenine TimeField sınıfını atadık. Sütun adını “visitor_time” olarak ayarladık ve veritabanına kayıt yapıldığında o anki zamanı sütuna yazması için auto_now_add parametresini True olarak belirledik.

Meta sınıfında ise OnlineCounter sınıfıyla ilgili düzenlemeler yapıyoruz. django.contrib.admin uygulamasını kullananların yönetici panelinde uygulamamızı “Online Counter” olarak görmeleri için verbose_name_plural değişkenini oluşturuyoruz ve tablo adını db_table değişkenine girdiğimiz değer ile online_counter yapıyoruz.

Şimdi uygulama dizinimizde middleware.py adında bir dosya oluşturuyoruz ve şunları yazıyoruz:

from onlinecounter.models import OnlineCounter
from datetime import datetime, time

class OnlineCounterMiddleware(object):
    def process_request(self, request):
        now_time = datetime.now().time()
        limit = time(now_time.hour, now_time.minute-5, now_time.second, now_time.microsecond)
        OnlineCounter.objects.filter(visited_time__lt=limit).delete()
        online, create = OnlineCounter.objects.get_or_create(ip=request.META["REMOTE_ADDR"])
        if request.user.is_authenticated():
            online.is_user = True
        else:
            online.is_user = False
        if not create:
            online.visited_time = now_time
        online.save()
        request.online = self

    def total(self):
        total = OnlineCounter.objects.all().count()
        return total

    def guest(self):
        guest = OnlineCounter.objects.filter(is_user=False).count()
        return guest

    def users(self):
        users = OnlineCounter.objects.filter(is_user=True).count()
        return users

models.py modülümüzü ve datetime modülünün datetime ve time fonksiyonlarını içe aktardık ve OnlineCounterMiddleware adında bir sınıf oluşturduk.

Django, her istek(request) yaptığında projeye ekli middleware sınıflarının process_request() methodunu çağırır. Bu da siteye giren herkesin sayacımız tarafından yakalanmasını sağlar. Php de olduğu gibi gerekli her php dosyasına kod eklemek zorunda kalmayız.

process_request() methodumuz çağırılacağına göre kodumuzu da bu method altına yazıyoruz.

Methoda request adında bir parametre atıyoruz. Bir kullanıcı istek yaptığında gerekli verileri Django, methodun bu parametresine atamaya çalışır.

now_time değişkenine istek yapıldığı anda ki zamanı öğrenmek için gerekli kodu yazıyoruz. limit değişkenine ise bir ziyaretçinin kaç dakika işlem yapmadığında veritabanından atılacağını belirten zamanı ayarlıyoruz. Hemen altındaki satırda limit değişkenindeki zamanın veritabanındaki zamandan küçük olan ziyaretçileri veritabanından siliyoruz. filter() methoduna girdiğimiz visited_time değişkenine eklediğimiz __lt ise “< " operatörünün sihirli method adı verilen methodlardaki adını temsil ediyor. Bu sayede zaman karşılaştırılmasını yapıyoruz.

Bir sonraki satırda ise get_or_create() methodu ile eğer request.META["REMOTE_ADDR"] ile belirtilen ziyaretçi sitede ise verisini çek, yoksa veri oluştur diyoruz. Geriye dönüş olarak bir tuple döndürür. Tuple verisinin ilk elemanı OnlineCounter nesnemiz, ikincisi ise veri çekildiyse False veri oluşturduysa True olur. Bu verileri de online ve create değişkenine pay ettik.

request.user.is_authenticated() kodu bize kullanıcı girişi yapıldıysa if blokunu isletmemizi sağlar ve is_user niteliğini True olarak ayarlarız. Giriş yapılmadıysa else bloku çalışır ve is_user niteliğini False olarak ayarlarız. Sonraki if blokunda ise eğer veri oluşturulmayıp çağırıldıysa, ziyaretçinin ziyaret zamanını güncelleriz.

online.save() ile değişiklikleri kaydediyoruz ve request e online adında bir nitelik oluşturup "self" ile sınıfımızı atıyoruz.

Oluşturduğumuz total() methodunda bütün veriyi çağırıp nesnemizin count() methoduyla kaç çevirimiçi kişi olduğunun verisi alıyoruz. guest() ve users() methodlarında ise OnlineCounter sınıfının is_user niteliğini kullanarak misafir mi, üye mi diye filtreleme yapıyoruz ve sonucu döndürüyoruz. Middleware sınıfımızla işimiz bu kadar.

Şimdi proje dizinine dönüp views.py adında bir dosya oluşturun ve şu şekilde yazın:


from django.shortcuts import HttpResponse

def main(request):
    online = """<p>Toplam: %s
    <p>Misafir: %s</p>
    <p>Kullanıcı: %s</p>"""%(request.online.total(), request.online.guest(), request.online.users())
    return HttpResponse(online)

urls.py dosyasını ise şöyle düzenleyin:

from django.conf.urls import patterns, include, url

urlpatterns = patterns('',
    url(r'^onlinecounter/$', 'views.main'),

)

settings.py dosyasına ise aşağıdaki şekilde düzenleyin:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': 'visitors.db', # veritabanı ayarları.

MIDDLEWARE_CLASSES = (
    'onlinecounter.middleware.OnlineCounterMiddleware', # middleware sınıfını ekleyin.
)

INSTALLED_APPS = (

    'onlinecounter', # uygulamamızı ekliyoruz.
)

Uygulamamız hazır olduğuna göre veritabanı tablomuzu eklemek için

python manage.py syncdb

komutunu veriyoruz ve ardından

python manage.py runserver

komutunu verip sunucuyu başlatıyoruz. İnternet tarayıcınızın adres çubuğuna localhost:8000/onlinecounter/ yazarak sonucu görebilirsiniz. admin uygulaması ekliyse ve giriş yaptıysanız kullanıcı sayacında, aksi halde misafir sayacında gözükeceksiniz. middleware sınıfımız sayesinde de istediğiniz bir template dosyanıza

{{ request.online.total }}
{{ request.online.guest }}
{{ request.online.users }}

şeklinde yazarak sonucu görebilirsiniz. Anlattığım gibi bir modül yazdım ve github hesabımda proje oluşturdum ve 1.0 sürümü ile kullanıma hazır.

easy_install django-online-counter
ya da
pip install django-online-counter

komutlarıyla kurabileceğiniz gibi

git clone https://mthnzbk@github.com/mthnzbk/django-online-counter.git

komutuyla dosyaları indirip

python setup.py install

ile kurabilirsiniz. Tabii ki bunları yapabilmeniz için; easy_install için python-setuptools paketini, git için git paketini, pip için ise

easy_install pip

komutuyla pip uygulamasını kurmanız gerekmektedir...

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.

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
25
Kas
Bu ders aracılığıyla SFML'nin Python bağlayıcısının nasıl derleneceğini, kurulacağını ve kullanılacağını öğrenebilirsiniz.


Yeni Python Bağlayıcısı
SFML 2 ile birlikte PySFML 2 isminde yeni bir Python bağlayıcısı geliştirilmeye başlandı. Daha önceki resmi bağlayıcıysa artık geliştirilmiyor.

Bastien'in geliştirmekte olduğu bu yeni bağlayıcı Python için C eklentileri yazmayı kolaylaştıran bir dil olan Cython ile kodlanıyor. Her ne kadar henüz resmi sürüm çıkmamış olsa da SFML 2'deki değişikliklere göre PySFML 2'da güncellemeler yapılıyor. Daha geniş bilgi için SFML forumlarındaki şu başlığa veya PySFML 2'nun GitHub üzerindeki proje sayfasına bakabilirsiniz.


Python Bağlayıcısının Kurulumu
PySFML 2 kısa bir süre önce Happy Kitty üzerinde Pardus için paketlendi. Pardus kullanıyorsanız PySFML 2'yu kolayca yükleyip kullanmaya başlayabilirsiniz. Arch kullanıcıları da AUR üzerinden yükleme yapabilir. Diğer dağıtımlar ve işletim sistemlerinde nasıl kurulum yapılacağını da PySFML 2'nun kurulum belgesinden öğrenebilirsiniz.


Pencere Oluşturmak
PySFML'de pencereler sf.RenderWindow sınıfıyla oluşturuluyor. Bu sınıf pencerimizi doğrudan oluşturmak için bazı yararlı yapıcılar sunmaktadır. Örnek bir kullanım aşağıdaki gibidir:
window = sf.RenderWindow(sf.VideoMode(800, 600, 32), 'PySFML Penceresi')
Burada pencerimizi temsilen window isminde yeni bir değişken oluşturuyoruz. Kullanılan paremetreleri şu şekilde açıklayabiliriz:
  • Kullanılan ilk parametre sf.VideoMode ve pencere için seçilen video kipini belirtiyor. Yukarıdaki örnekte 800x600 piksel büyüklüğünde ve 32 bit derinliğinde bir pencere için değerler görülüyor.
  • İkinci parametreyse pencere başlığıdır.
Pencereyi daha sonra oluşturmak veya farklı parametrelerle tekrar oluşturmak isterseniz sf.RenderWindow.create() metodunu kullanabilirsiniz:
window.create(sf.VideoMode(800, 600, 32), 'PySFML Penceresi');
Yapıcı ve sf.RenderWindow.create() metodu ayrıca iki ek paremetre daha almaktadır. Bunlardan biri pencerenin stilini ayarlamak ve diğeri de daha gelişmiş grafik seçeneklerini ayarlamak içindir. Gelişmiş grafik ayarlarına bu derste fazla değinilmeyecektir. Stil parametresiyse sf.Style bayraklarının (None, Titlebar, Resize, Close ve Fullscreen) bir kombinasyonu olabilir. Öntanımlı değer Resize | Close'dur.
# Bu tam ekran bir pencere oluşturur
window.create(sf.VideoMode(800, 600, 32), 'PySFML Penceresi', sf.Style.FULLSCREEN);

Video Kipleri
Yukarıdaki örnekte video kipi için fazla düşünmedik çünkü pencere kipinde çalışıyorduk, her boyut sorunsuzca kullanılabilir. Fakat tam ekran kipinde çalışmak istiyorsak yalnızca desteklenen kiplerden birini seçmeliyiz. sf.VideoMode.get_fullscreen_modes() sınıf metodu tüm desteklenen tam ekran kiplerinin listesini döndürmektedir. Listedeki öğeler en iyiden en kötüye doğru sıralanmaktadır, böylece sf.VideoMode.get_fullscreen_modes()[0] her zaman en yüksek kaliteli kip olur:
window = sf.RenderWindow(sf.VideoMode.get_fullscreen_modes[0], 'PySFML Penceresi', sf.Style.FULLSCREEN)
Pencere kipini seçmesi için kullanıcıyı özgür bırakıyorsanız, girilen değerleri uygulamadan önce kontrol etmelisiniz. Bunun için sf.VideoMode.is_valid()'i kullanabilirsiniz:
mode = bir_yerlerden_kipi_al() 
if not mode.is_valid():
    # Hata...
Kullanılan masaüstü kipi de sf.VideoMode.get_desktop_mode() sınıf metoduyla elde edilebilir.


Ana Döngü
Oyunumuzun döngü iskeletini yazmaya başlayalım:

# Kurulum kodu
window = sf.RenderWindow(sf.VideoMode(640, 480), 'PySFML Penceresi')
# ... 
while True:
    # Olayları yönet
    # ... 
    window.clear(sf.Color.WHITE)
    # Çizimleri yap
    # ... 
    window.display()

sf.RenderWindow.clear() pencereyi belirtilen renkle doldurur. sf.Color yapıcısıyla özel renk nesneleri oluşturabilirsiniz. Örneğin pembe bir arkaplan istiyorsanız window.clear(sf.Color(255, 192, 203)) yazabilirsiniz. sf.RenderWindow.display() çağrımı ise pencerenin içeriğini günceller.

Yukarıdaki kod pek doğru görünmeyebilir çünkü pencereyi aynı arkaplan rengiyle boyayıp durmak dışında pek bir şey yapmayan bir döngüye sahibiz yalnızca. Endişelenmenize gerek yok, çok yakında biraz daha işe yarar şeyler yazınca daha mantıklı görünmeye başlayacaklar.

Yukarıdaki gibi bir kod parçasını çalıştırıp işlem süreçlerini kontrol ederseniz bu küçük programın işlemciyi %100 olarak kullandığını görebilirsiniz. Bu pek de sürpriz değildir, yazdığımız döngü tam olarak bunu yapmaktadır. Bu durumu düzeltmek için sf.RenderWindow.framerate_limit kullanılabilir:
window.framerate_limit = 60
Bu satır SFML'e pencereyi saniyede 60 defadan fazla güncellememesini söylemektedir.

Aşağıdaki PySFML ile yazılmış örneği inceleyerek öğrendiklerinizi pekiştirebilirsiniz.

#!/usr/bin/python
# -*- coding: utf-8 -*- 
import sf 
def main():
    window = sf.RenderWindow(sf.VideoMode(800, 600),
                             'PySFML Penceresi',
                             sf.Style.FULLSCREEN)
    window.framerate_limit = 60
    running = True
    texture = sf.Texture.load_from_file('python-logo.png')
    sprite = sf.Sprite(texture)
    sprite.origin = (sprite.width / 2, sprite.height / 2)
    sprite.move(window.width / 2, window.height / 2) 
    while running:
        for event in window.iter_events():
            # Uygulama kapandığında veya
            # kullanıcı Escape tuşuna bastığında çalışmayı durdur
            if (event.type == sf.Event.CLOSED or
                (event.type == sf.Event.KEY_PRESSED and
                 event.code == sf.Keyboard.ESCAPE)):
                running = False 
        window.clear(sf.Color.WHITE)
        window.draw(sprite)
        window.display()
    window.close()
if __name__ == '__main__':
    main()

Kısaca SFML'yi Python ile nasıl kullanacağımızı gördük. Daha fazlası için diğer örnekleri inceleyebilir ve UPA belgelerine göz atabilirsiniz.


Kaynaklar


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.

20
Eki

Uzun süredir geliştirmediğim Parçala adlı uygulamamın yeni sürümünü çıkarmış bulunuyorum. Parçala, Hj-Split ile aynı işi gören büyük boyutlu dosyaları parçalara ayırır, birleştirir ve dosya özetini çıkarır; bu sayede birleşen dosya doğru birleşmiş mi diye kontrol etmiş olursunuz. Aşağıda kullanımını gösteren bir video paylaşıyorum…

Doğrulama yaparken neden ikinci sefer dialogu açtığıma gelirsek; dosya özetinin değişmemesi kullanıcıları yanıltabilir diye doğruluğunu kanıtlamak için. Ayrıca gtk-qt tema dönüşümünden kaynaklanan bir sorundan dolayı(sanırım) dosya özetini görebilmek için girdi alanına tıklamam gerekti. Kde üzerinde ve Windows altında sorun yaşanmayacağını düşünüyorum. Uygulamanın kaynak kodlarına buradan ulaşabilirsiniz. Uygulamayı dener, hata alırsanız ve/veya şunu şöyle yap demek isterseniz proje sayfasından istekte bulunabilirsiniz(issue).

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. Virux – GNU/Linux için bir antivirüs yazılımı :P
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
23
Eyl

Ofis içerisinde, ya da evinizde bir bilgisayardan diğerine dosya almak istiyorsunuz diyelim. Bunun için Samba, Scp (secure copy), FTP gibi yöntemler mevcut ancak bunların önceden ayarlanması ve üzerinde zaman harcanması gerekiyor. Bunun yerine basit olarak bri dizindeki dosyaları HTTP üzerinden sunmaya yarayan ve python ile beraber gelen basit bir sınıf mevcut, SimpleHTTPServer.

Tek yapmanız gereken bir konsol açmak ve dosyalarını paylaştırmak istediğiniz dizine girmek. Sonrasında konsola python -m SimpleHTTPServer 8080 yazarak o dizindeki dosyaları 8080 numaralı porttan sunmaya başlayabilirsiniz.


26
Ağu

Uzun uğraşlar sonucunda yeni sürümü yayınlamaktan mutluluk uyuyorum :) Bu sürümde Virux u platform bağımsız olarak sunuyorum… Bu sürümle gelen yenilikler ise şöyle:

* Yeni bir dialog eklendi.
* Sistem menüsüne Kapat ve Açılışta başlat seçeneği eklendi.
* Bu ayarların kaydedilmesi için QSettings sınıfı kullanıldı.
* Dialogların Escape tuşuyla kapanması önlendi. Bu yüzden uygulama kapanıyordu.

En son maddeyle beraber PyQt bilen arkadaşların katkı sağlamasında gerekli şartlara bir yenisi daha eklenmiş oldu.

Her QDialog’u genişleten sınıfınızda bu şekilde bir method tanımlanması gerekmektedir.

def keyPressEvent(self, event):
    if event.key() == Qt.Key_Escape:
        pass

Qt.Key_Escape i kullanabilmek için QtCore modülünde bulunan Qt’yi import etmeniz gerekmektedir…

Unutmayın QDialog’u miras alan sınıfınızın adı DMessage olmalıdır; Python dosyasının adı önemli değildir…

Yeni sürüme buradan ulaşabilirsiniz. Yalnız Windows kullanıcıları için derlenmiş halini veremiyorum. Çünkü derlemeden sonra bir takım hatalar oluşuyor.

Windows sisteminizde Python ve PyQt kurulu ise virux.py dosyasını virux.pyw yaparak çalıştırınız ki; açılışta çalıştır seçeneğini aktif yapınca işletim sisteminiz açılınca konsol çıkmasın…

Dialog olarak katkı sağlamak isterseniz belirtilen kurallara uyarak yazdığınız kodları iletişim sayfasından ya da bu yazıya yorum yazarak ulaştırabilirsiniz. Python dosyanıza __author__ değişkeni tanımlayıp isminizi yazmanız da katkıyı yapanın kim olduğunu belirtecektir…

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. Virux – GNU/Linux için bir antivirüs yazılımı :P
23
Ağu
Sumru, (bilmeyenler için kısaca özetlersek) Özgürlük İçin Ajans bölümü için yazılmış, basit bir PyQt4 uygulamasıdır. Bu sürüme eklenen özellikler şöyle;
  • Yorumlar Öİ Kullanıcı resmi ile birlikte gösterilebiliyor
  • İndirme işlemine durum çubuğu eklendi
  • Arayüzde iyileştirmeler yapıldı.
Daha fazla bilgi: http://code.google.com/p/sumru/

    19
    Ağu

    Virux adında çok önceleri acemice bir betik yazmıştım. O günlerde bir kaç kişi bunu geliştirmemi söylemişler ve örnek sunmuşlardı…

    Son bir kaç ay önce bunun hatırlatılmasıyla daha güzel bir uygulama yazmaya karar verdim. Üzerine pek düşmedim ve ancak keyfim olursa kodladım ve nihayet kullanılabilir bir duruma geldi…

    Virux, aslında bir eğlence yazılımı. KNazar gibi bir süs olarak sistem çubuğunda duruyor ve hareketli bir ikona sahip. Ara sıra -şu an 4 adet olan- dialoglar ekrana çıkıyor ve biraz olsun gülümsetmeye çalışıyor…

    Yazılımın kodlarına buradan ulaşabilirsiniz. Son sürümü ise buradan indirebilirsiniz.

    Uygulama PyQt ile yapılmıştır. Sizde PyQt biliyorsanız dialog olarak katkı sağlayabilirsiniz.

    Dialoglarınızın kabul edilebilmesi için bazı şartları yerine getirmesi gerekmektedir.

    1. QDialog’u genişleten sınıfınızın adı DMessage olmalıdır. __init__ methodu ise aşağıdaki gibi olmalıdır.

    class DMessage(QDialog):
        def __init__(self, parent):
            QDialog.__init__(self, parent)
    

    2. Her dialog sınıfında closeEvent() methodu tanımlanmalı ve içeriği şöyle olmalıdır.

    def closeEvent(self, event):
        event.ignore()
        self.hide()
    

    Karşılanması gereken zorunlu şartlar bunlardır. Sınıfı tutan Python dosyasının adı önemli değildir(diğer Python dosyalarıyla çakışmamalıdır), DMessage den başka sınıf tanımlamak önemli değildir; Uygulama sadece DMessage sınıfını kullanacaktır.

    Yukarıdaki iki şartı sağlayarak yazdığınız kodları bu yazı altında yorum olarak yazabilir ya da iletişim sayfasından irtibat kurabilirsiniz… Kullandığınız cümleler ve kodun güzelliğine göre kodunuzun eklenme ihtimali artacaktır.

    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ı yok.

    7
    Ağu

    Genelde Python ile kodladığımız bir yazılımı kaynak kodlarıyla paylaşırız. Python öğrenenlerde genellikle açık kaynak ve/veya özgür yazılım olarak kodlarını yayınlarlar. Eğer siz diğer gruba dahilseniz ya da en azından ilk başta kaynak kodlarınızı incelemek isteyenlerden; kötü yazılmış kodlarınızı saklamak isteyenlerdenseniz okumaya devam edin…

    Amacı, kaynak kodları kapalı bir yazılım geliştirmek isteyen birisi en basitinden py uzantılı dosyaları derleyerek pyc olarak dağıtabilir ya da py2exe, pyinstaller ve cx_freeze gibi modüllerle çalıştırılabilir binary dosyaya dönüştürebilir.

    Bizim amacımız ise masumca :) Amacımız python modüllerimizi ve/veya paketlerimizi tek bir yerde toplamak ve kalabalık yapmamak. Örneğin çalıştıracağımız py uzantılı dosyamızın adı oyun.py olsun ve aynı dizinde “lib” adında bir dizin içinde ise __init__.py, gui.py, ai.py dosyaları olsun. Bu durumda dosya yapımız şöyle olacaktır:

    oyun.py
    lib/
    ---- __init__.py
    ---- ai.py
    ---- gui.py
    

    lib dizinini zip dosyası haline getireceğiz ve farklı bir isim ve uzantıyla kaydedeceğiz. Sizin bu yöntemi kullandığınızı bilmeyen acemiler kaynak kodlarınızı bulamayacaktır :) Amacım kapalı kaynak yazılım yazmayı özendirmek değil. Şu güne kadar ne kodladıysam hepsini gpl v3 ile lisanslamışımdır.

    Konuya dönelim ve bu zipleme işini de zipfile modülü ile yapalım. Bu modülü bilmeyenler daha önce yazdığım yazımı inceleyebilirler.

    import zipfile
    
    zip = zipfile.ZipFile('save.data',"w",zipfile.ZIP_DEFLATED)
    zip.write("lib/__init__.py")
    zip.write("lib/ai.py")
    zip.write("lib/gui.py")
    zip.close()
    

    lib diziniyle aynı dizinde bu betiği çalıştırırsanız save.data adında bir zip arşivi oluşacaktır. Şimdi bu save.data adlı arşivimizi oyun.py de çağıralım.

    import sys
    
    sys.path.insert(0, "save.data")
    
    import lib.ai
    from lib import gui
    

    Görüldüğü gibi fazladan iki satır kod yazıp arşiv dosyamızı path e ekledik ve kodları gizlemiş olduk. Siz siz olun kodlarınızı özgür yapın. Sonra bu yazıyı bahane ederek gezegenlerden atılmak istemem :) Sürekli pygame yazısı yazdığım için değişiklik olsun diye bu özelliği anlattım. py2exe ile uygulamanızı çalıştırılabilir yaptıysanız belki dizin içinde zip dosyası görmüşsünüzdür. İşte bu zip dosyası da benim anlattığım gibi kullanılmaktadır.

    Eğer modüllerinizde aynı dizin içinde, yahut zip arşivinin içine gelecek şekilde bir dosya okumaya ve/veya yazmaya çalışırsanız hata alırsınız. Pygame ile resim dosyasını göstererek Surface nesnesi oluşturmayı denerseniz hata alırsınız. Benim deneyimlerimden bunlar açığa çıktı. Bu yöntemi kullanacaksanız bunun gibi hata çıkaracak unsurlara dikkat ediniz.

    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 zipfile Modülü
    PyQt4 'de uzak sunucudaki resimleri herhangi bir araç da göstermek için urllib2'den yararlanacağız. Tabi bunun dışında loadFromData özelliğini kullanacağız. İşte kodlar.

    import urllib2
    imageUrl = urllib2.urlopen("http://www.ozgurlukicin.com/media/img/ozgurlogo.png")
    imageData = imageUrl.read()
    imageUrl.close()
    image = QtGui.QPixmap()
    image.loadFromData(imageData)
    item = QtGui.QListWidgetItem(self.listWidget)
    item.setIcon(QtGui.QIcon(image))
    İlk önce görselimizin bulunduğu adresi okuttuk ve image.loadFromData() içerisinde kullandık. Ardından hangi Qt aracına ekleyecek isek ona görseli ekledik.

    Kaynak: http://www.riverbankcomputing.co.uk/static/Docs/PyQt4/html/qpixmap.html#loadFromData
    31
    Tem
    Sumru, Özgürlük İçin Ajans bölümünü takip eden basit bir yazılımdır. Siteye eklenen ajansları bularak kendi listesine özet, sunucu ve uzunluk gibi bilgileri göstererek ekliyor ve mp3, ogg formatlarında indirebilmenizi ve dinleyebilmenize olanak verir. Şimdilik sadece siteye en son eklenen ajans ile dokuz tane en son ajans bölümlerini dinlemenize olanak veriyor. Programı işlev olarak gereksiz görebilirsiniz ama ajans için yazılmış bu program Özgürlük İçin'e değişik bir hava katıyor. :)

    İndirmek ve kurulum için proje sayfası: http://code.google.com/p/sumru/



    19
    Tem

    Bu başlık sanki bilge-katalog’un yeni sürümü hazırmış gibi bir izlenim veriyor. Ama başlığın verdiği izlenim biraz hatalı. Birazdan uzunca açılayacağım neden hatalı olduğunu.

    Eski yazılarımda bahsetmişimdir bilge-katalog’dan. Şimdi geri bağlantı vermekle uğraşmak istemiyorum. Bu yazılım benim arşivlerimdeki dosyalara ulaşmamı kolaylaştırmak için yazılmaya başlamıştı. 0.1 sürümü iş görür derecedeydi. Bu sürümdeki kod yazımımı beğenmediğim için baştan yazmaya karar vermiştim. Sıra o kararı uygulamaya geldi. 0.2 sürümü üzerinde çalışıyordum. Henüz 0.1 sürümünün tüm özelliklerine kavuşmamış olsa da yeni bazı özellikler getiriyordu.

    0.2 sürümünü tamamlayamadığımdan yayınlayamadım. Neden tamamlayamadım? Sebep çok :D En büyük sebep okuldaki derslerin ağır basması. Okuldan geriye kalan zamanda da o zamanlar genelde kısa olduğu için kodlara girişmek istemedim.

    Neyse tatile girince bolca vaktim olsa da 2 gün önce kodlara bakmaya başladım. Kodlara baktığımda gördüm ki bu yazılımın bir geleceği yok veya olsa da çok uğraştıracak bir gelecek olur. İşte bu yüzden yine baştan yazmaya karar verdim. Yeni bir yapıyı kullanacak şekilde yeni baştan yazmaya karar verdim.

    Karar vermesine verdim de bu defa kendim aklıma geleni yazmayacağım. Çünkü kendi aklıma geleni daha uygulamanın yarısına gelmişken değiştiriyorum, uygulamanın bir kısmı boşa gidiyor. Bu defa yazmaya başlamadan önce bu yazıya yorum olarak veya benimle başka ortamlarda yazışarak söylediğiniz fikirlerin de üzerinde durarak bir yapı oluşturacağım.

    Öncelikle size eski kullandığım yapıdan biraz bahsedeyim ki sizin aklınızda da bir şeyler canlansın. Bu yazılımın yaptığı iş şu:

    • Belirtilen dizindeki (/media/dvdrom gibi) tüm dizin ve dosya yapısının sadece isim ve bazı özelliklerini bu dosya ve dizin yapısıyla bir veritabanına ekliyor.
    • Daha sonra arama yapıldığında bir liste verip hangisinin hangi katalogda olduğunu söylüyor. Mesela: “mehter marşı” diye aratıyorum, yazılım “Müzikler 3 dvd’sinde” diyor. Hatta adresine kadar söylüyor(katalog://marşlar/mehter marşı/ gibi).
    • Aynı şekilde dvd’yi sanki bilgisayara takmış gibi dvd dizin ve dosya yapısında gezebiliyorsunuz.
    • Gereksiz gördüğünüz dosya, dizin ve kataloğu silebiliyorsunuz. (adı nokta ile başlayan gizli dosyaları silmek gibi)
    • Ayrıca kitap arşiviniz(kütüphaneniz demek daha hoş olurdu sanki) içinde bu yazılımı kullanabiliyorsunuz. Bunun için boş bir katalog oluşturup içine kitap eklemeniz yeterli. Hatta ödünç verme sistemi de eklemiştim.

    Yazılımın önceki halinin yapabildiği işler bunlardı. Benim yeni oluşturacağım yapı biraz bu özellikler tamamlar ve biraz da lüzumsuz kısımları silecek şekilde olacak. Düşündüğüm bazı şeylerden bahsedeyim:

    • Ayrıntılı dosya özellikleri almak için eklenti yükleme şeklindeki bir yapıya geçmeyi düşünüyorum.
    • Yazılım kullanıcı tarafından fazlaca özelleştirilebilsin, hatta yazılım kullanıcıya muhtaç kalsın. Birçok şeyi kullanıcının yapmasını istesin. Bu birçok kullanıcının istemeyeceği bir şey ama kullanıcıyı aptal gibi düşünmekten iyidir.

    Şimdilik aklıma gelenler bunlar. Sizin de bir şeyler katmanızı istiyorum. Bu yüzden bu konuda fikri, bilgisi, vs’si olan lütfen yorumla veya başka bir yöntemle bana ulaşıp fikrini bildirsin.

    Yakın geçmiş zamanda Pindir'in kararlı sürümünü (sürüm 4.5.3'ü) indirme adresini proje sayfasına ve çeşitli internet adresleri ortamına ekledim. Ayrıca Pardus için depoya alınmasını da istedim. Bu kadar hatırlatma yeter sanırım.:) Başlıkta da belirttiğim gibi Pindir'e yeni bir özellik ekledim. Aslında bu özelliği en başından beri eklemek istiyordum fakat bir türlü başaramıyordum. Dün tekrar denedim ve olumlu sonuçlar elde ettim. Çoğu yerde de belirttiğim gibi Python ile hobi olarak ilgileniyorum. İyi, (orta derece bile) bilmediğimden bu kadar zaman aldı bu özellik. Lafı fazla uzatmadan söyleyeyim eklediğim özelliği. Artık Pindir YouTube'dan video araması yapabiliyor ve bulunan videoları indirebiliyor. Şimdilik yeni kodlandığından bir çok eksiği var. Henüz alfa aşamasındadır diyebiliriz. Video aramada şimdilik altı tane video buluyor ve bunları video başlıkları ve önizlemeleri ile listeye ekliyor. Yalnız şöyle saçma bir sorunum var; önizlemeleri sisteme indirterek kullanabiliyorum. Uzak sunucudan resim QListWidget'a nasıl eklenir bilemiyorum, bu yüzden şimdilik bu işlemi resimleri indirerek çözdüm. Dediğim gibi henüz çok eksiği var. Biraz daha geliştirdikten sonra indirme adreslerini vereceğim.
    Yardım etmek isteyen olursa bana ulaşabilirse sevinirim.
    Şimdilik iki tane resmini vereyim.


    16
    Tem
    PyQt arayüzlerin de root olmak benim için can sıkıntısı bir şeydi. Çok önceleri bile kafama takılıyordu bu işlem. Python'da "os.system" gibi komutların içinde root gerektiren komutları verince konsola bağımlı kalıyordum. Bugün araştırma yaparken güzel bir kod parçası buldum. İşe de yarıyor. Tarayıcı geçmişlerini kullanmadığımdan kodu bulduğum siteyi kaybettim. Bu yüzden kaynak veremiyorum.  Ama bu güzel kodu paylaşmayı düşünüyorum. :)
            mypass =  "Kullanıcının Parolası"
            sudo_command
    = "sudo python setup.py install"
            os
    .system('echo %s|sudo -S %s' % (mypass, sudo_command))
    Güzel öyle değil mi?