Bir programın çıktısını sunmanın birkaç yolu vardır; veri yazdırılabilir ya da gelecekte kullanılabilecek şekilde bir dosyaya kaydedilebilir. Bu bölümde giriş ve çıkış ile ilgili olanakların bazılarına değineceğiz.
Buraya kadar değerleri yazdırmanı iki yolunu gördük: deyim
ifadeleri ve print deyimi. Üçüncü bir yol da dosya
nesnelerinin write() metodudur. Standart çıktı dosyasına
sys.stdout
şeklinde atıfta bulunulabilir.
Çoğu zaman boşluklar ile biribirinden ayrılmış değerlerden daha iyi
biçimlendirilimiş bir çıktıya ihtiyaç duyulur. Çıktınızı
biçimlendirmenin iki yolu var. İlki bütün karakter dizisi işlemlerini
dilimleme ve birleştirme ile yapıp istediğiniz herhangi bir biçimi
elde etmek. string standart modülü
karakter dizilerinin istenen sütun genişliğine kadar boşluklar ile
doldurulmasını sağlayan ,daha sonra değineceğimiz, bazı faydalı
fonksiyonlara sahiptir. İkinci yol ise sol argümanı bir karakter
dizisi olan %
islecini kullanmaktır. %
isleci
sol argümanını sağdaki argümanına uygulanacak sprintf()
tarzı biçim karakter dizisi olarak yorumlar ve biçimleme işleminden
sonra bir karakter dizisi geri döndürür.
Sayısal değerleri karakter dizisine çevirmek için ise değer
repr() veya str() fonksiyonuna geçirilebilir ya da
ters tırnak işareti ( ``
) içine alınabilir (
repr() ile aynı etkiyi yapar).
str() fonksiyonu değerlerin insan tarafından okunabilir gösterimini geri döndürürken, repr() fonksiyonu ise yorumlayıcı tarafından okunabilir gösterimini geri döndürür (veya uygun sözdizim yok ise SyntaxError istisnası oluşturur). İnsan için anlam ifade edecek bir gösterimi bulunmayan nesneler için str() fonksiyonu repr() ile aynı değeri döndürür. Rakamlar, listeler ve sözlükler gibi yapılar ile daha pek çok değer için her iki fonksiyon da aynı sonucu verir. Karakter dizileri ve kayar noktalı rakamlar ise iki farklı gösterime sahiptir.
İşte birkaç örnek:
>>> s = 'Hello, world.' >>> str(s) 'Hello, world.' >>> `s` "'Hello, world.'" >>> str(0.1) '0.1' >>> `0.1` '0.10000000000000001' >>> x = 10 * 3.25 >>> y = 200 * 200 >>> s = 'The value of x is ' + `x` + ', and y is ' + `y` + '...' >>> print s The value of x is 32.5, and y is 40000... >>> # Ters tırnaklar sayılar dışındaki tipler ile de çalışır: ... p = [x, y] >>> ps = repr(p) >>> ps '[32.5, 40000]' >>> # Karakter dizisinde ise tırnaklar ve ters bölü işareti eklenir: ... hello = 'hello, world\n' >>> hellos = `hello` >>> print hellos 'hello, world\n' >>> # Ters tırnakların argümanı bir demet de olabilir: ... `x, y, ('spam', 'eggs')` "(32.5, 40000, ('spam', 'eggs'))"
Sayıların kare ve küplerinden oluşan bir tablo yazdırmanın iki yolu vardır:
>>> import string >>> for x in range(1, 11): ... print string.rjust(`x`, 2), string.rjust(`x*x`, 3), ... # Üst satırın sonundaki virgüle dikkat edin. ... print string.rjust(`x*x*x`, 4) ... 1 1 1 2 4 8 3 9 27 4 16 64 5 25 125 6 36 216 7 49 343 8 64 512 9 81 729 10 100 1000 >>> for x in range(1,11): ... print '%2d %3d %4d' % (x, x*x, x*x*x) ... 1 1 1 2 4 8 3 9 27 4 16 64 5 25 125 6 36 216 7 49 343 8 64 512 9 81 729 10 100 1000
Sütunların arasındaki bir karakterlik boşluk print tarafından eklenir; argümanların arasına daima bir boşluk karakteri eklenir.
Bu örnek karakter dizilerinin başını boşluklar ile doldurup bunları sağ tarafa dayayan string.rjust() fonksiyonunu kullanmaktadır. Buna benzer string.ljust() ve string.center() fonksiyonları da vardır. Bunlar bir şey yazdırmaz; sadece yeni bir karakter dizisi geri döndürürler. Verilen karakter dizisi uzun ise kırpılmaz ve aynen geri döndrürlür; bu sütunlarınızın bozulmasına sebep olmasına rağmen hatalı bir değer göstermekten iyidir. Büyük bir değeri kırpmayı gerçekten istiyorsanız dilimleme ile bunu yapabilirsiniz ("string.ljust(x, n)[0:n]" gibi ).
string.zfill() fonksiyonu ise rakamlar içeren karakter dizilerinin başını sıfırlar ile doldurur. Bu fonksiyon artı ve eksi işaretlerini de dikkate alır:
>>> import string >>> string.zfill('12', 5) '00012' >>> string.zfill('-3.14', 7) '-003.14' >>> string.zfill('3.14159265359', 5) '3.14159265359'
%
isleci şu şekilde kullanılır:
>>> import math >>> print 'PI sayısının yaklaşık değeri: %5.3f' % math.pi PI sayısının yaklaşık değeri: 3.142
Karakter dizisinin içinde birden fazla biçim varsa sağ operand olarak bir demet kullanmak gerekir:
>>> table = {'Sjoerd': 4127, 'Jack': 4098, 'Dcab': 7678} >>> for name, phone in table.items(): ... print '%-10s ==> %10d' % (name, phone) ... Jack ==> 4098 Dcab ==> 7678 Sjoerd ==> 4127
Çoğu biçim aynı C dilindeki gibi çalışır ve doğru veri tipinin
geçirilmesi gerekir; bu yapılamaz ise bir istisna oluşur. %s
biçiminin kullanımı daha rahattır; verilen argüman karakter dizisi
değilse yerleşik fonksiyon str() ile karakter dizisine
dönüştürülür. Genişlik ya da hassasiyeti belirtmek için *
ile
bir tamsayı argüman kullanılabilir. C dilindeki %n
ve
%p
biçimler ise desteklenmemektedir.
Eğer bölmek istemediğiniz gerçekten uzun bir biçim karakter diziniz
varsa biçimlendirmek istediğiniz argümanlara konumu yerine ismiyle
atıfta bulunabilmeniz güzel olur. Bu aşağıda gösterildiği gibi
%(isim)biçim
şeklinde yapılabilir:
>>> table = {'Sjoerd': 4127, 'Jack': 4098, 'Dcab': 8637678} >>> print 'Jack: %(Jack)d; Sjoerd: %(Sjoerd)d; Dcab: %(Dcab)d' % table Jack: 4098; Sjoerd: 4127; Dcab: 8637678
Bu özellik bütün yerel değişkenlerin bulunduğu bir sözlük geri döndüren yerleşik fonksiyon vars() ile beraber kullanıldığında faydalı olur.
open() fonksiyonu bir dosya nesnesi geri döndürür ve genellikle iki argüman ile kullanılır: "open(dosya_adı, mod)"
>>> f=open('/tmp/workfile', 'w') >>> print f <open file '/tmp/workfile', mode 'w' at 80a0960>
İlk argüman dosya adını içeren bir karakter dizisidir. İkincisi ise
dosyanın nasıl kullanılacağını belirten karakterlerden oluşur. Erişim
modu dosyadan sadece okuma yapılacak ise 'r'
, sadece
yazma için 'w'
(anı isimli bir dosya zaten var ise bu silinir)
ve dosyanın sonuna eklemeler yapmak için 'a'
olur. 'r+'
modu dosyayı hem okuma hem de yazma yapmak için açar. mod
argümanı seçimliktir; kullanılamaması halinde 'r'
olduğu
varsayılır.
Windows ve Macintosh üzrinde moda eklenen 'b'
harfi dosyayı
binary modunda açar; yani 'rb'
, 'wb'
, ve 'r+b'
gibi modlar da vardır. Windows metin ve binary dosyaları arasında
ayrım yapmaktadır; metin dosyalarında okuma veya yazma işlemlerinde
satır sonu karakterleri otomatik olarak biraz değişir. Bu görünmez
değişiklik ASCII metin dosyaları için iyidir; anacak JPEG resimler
veya .EXE dosyalar gibi binary verileri bozar.
Bundan sonraki örneklerde f
adlı bir dosya nesnesinin önceden
yaratılmış olduğunu varsayacağız.
Dosyanın içeriğini okumak için belirli miktarda veriyi okuyup bunu
karakter dizisi olarak geri döndüren f.read(boy)
metodu
kullanılabilir. boy okunacak bayt sayısını belirleyen seçimlik
bir argümandır; kullanılmaması halinde dosyanın tamamı okunur.
Dosyanın sonuna gelindiğinde f.read()
boş bir karakter dizisi (
""
) geri döndürür.
>>> f.read() 'Dosyanın tamamı bu satırdan oluşuyor.\n' >>> f.read() ''
f.readline()
dosyadan tek bir satır okur. Satırın sonundaki
yeni satır karakteri (\n
) korunur; ancak dosya yeni bir satır
ile bitmiyor ise son satırda bu karakter silinir. Bu özellik geri
döndürülen değerin birden fazla anlama gelmesini engeller;
f.readline()
boş bir karakter dizisi geri döndürdüğünde dosyanın
sonuna ulaşılırken boş bir satır tek bir '\n'
karakteri ile
ifade edilir.
>>> f.readline() 'Bu dosyanın ilk satırı.\n' >>> f.readline() 'Dosyanın ikinci satırı\n' >>> f.readline() ''
f.readlines()
dosya içindeki bütün satırların bulunduğu bir
liste geri döndürür. Seçimlik parametre boy_ipucu kullanılması
durumunda ise dosyadan boy_ipucu kadar ve bundan bir satır tamamlamaya
yetecek kadar fazla bayt okunur ve bunlar yine satırlar listesi
şeklinde geri döndürülür.
>>> f.readlines() ['Bu dosyanın ilk satırı.\n', 'Dosyanın ikinci satırı\n']
f.write(karakter_dizisi)
metodu karakter_dizisi
içeriğini dosyaya yazar ve None
geri döndürür.
>>> f.write('Bu bir deneme satırıdır.\n')
f.tell()
dosya nesnesinin dosya içindeki konumunu belirten bir
tamsayı geri döndürür (dosyanın başından bayt cinsinden ölçülür).
"f.seek(uzaklık, nereden)" ile de dosyanın içinde
istenen konuma gidilebilir. Konum uzaklık ile referans noktası
nereden değerlerinin toplanması ile bulunur. nereden 0
olursa dosyanın başını, 1 o andaki konumu, 2 ise dosyanın sonunu
belirtir. nereden kullanılmaz ise 0 olduğu varsayılır ve
referans noktası olarak dosyanın başı alınır.
>>> f=open('/tmp/workfile', 'r+') >>> f.write('0123456789abcdef') >>> f.seek(5) # Dosyadaki 5'inci bayta git >>> f.read(1) '5' >>> f.seek(-3, 2) # Sondan 3'üncü bayta git >>> f.read(1) 'd'
Dosya ile işiniz bittiğinde metodunu f.close()
çağırarak
dosyayı
kapatabilir ve dosyanın işgal ettiği sistem kaynaklarını serbest
bırakabilirsiziz. f.close()
çağırıldıktan sonra dosya üzerinde
başka işlem yapmaya devam etmek mümkün değildir:
>>> f.close() >>> f.read() Traceback (most recent call last): File "<stdin>", line 1, in ? ValueError: I/O operation on closed file
Dosya nesnelerinin isatty() ve truncate() gibi pek sık kullanılmayan başka metodları da vardır.
Karakter dizileri kolayca dosyalara yazılıp dosyalardan okunabilirler.
Sayılar biraz zahmetlidir; çünkü read() metodu sadece
karakter dizileri geri döndürür ve bunların '123'
gibi bir
değeri alıp sayısal değeri 123'ü geri döndüren
string.atoi() fonksiyonundan geçirilmeleri gerekir.
Listeler, sözlükler ve sınıf
fertleri (class instances) gibi daha karmaşık veri türlerini dosyalara
kaydetmek isterseniz işler oldukça zorlaşır.
Programcıları karmaşık veri türlerini saklamak için kodlamak ve hata ayıklamak ile uğraştırmak yerine Python bu iş için pickle adlı standart modülü sağlar. Bu hayret verici modül neredeyse herhangi bir Python nesnesini (bazı Python kodu biçimlerini bile !) karakter dizisi ile ifade edilebilecek hale getirebilir ve bu halinden geri alabilir. Bu dönüşüm ve geri kazanım işlemleri arasında nesne bir dosyaya kaydedilebilir ya da ağ bağlantısı ile uzaktaki başka bir makineye gönderilebilir.
x
gibi bir nesneniz ve yazma işlemi için açılmış f
gibi
bir dosya nesneniz varsa bu nesneyi dosyaya aktarmanız için tek
satırlık kod yeterli olur:
pickle.dump(x, f)
Nesneyi geri almak için ise f
okumak için açılmış bir dosya
nesnesi olsun:
x = pickle.load(f)
Birden fazla nesnenin dönüştürülmesi gerekiyor ya da dönüştürülmüş olan nesnelerin dosyaya yazılması istenmiyor ise pickle farklı şekilde kullanılır. Bunları pickle modülünün dokümanlarından öğrenmek mümkündür.
pickle modülü saklanabilen ve başka programlar tarafından ya da aynı programın farklı çalışma zamanlarında kullanılabilecek Python nesneleri yapmanın standart yoludur. pickle modülü çok yaygın kullanıldığından Python genişletme modülleri yazan çoğu programcı matrisler gibi yeni veri tiplerinin doğru olarak dönüştürülebilir ve geri alınabilir olmasına özen gösterirler.