%%writefile deneme.txt
!
Ey Türk Gençliği
Birinci vazifen, 'ni,
Türk istiklâlini, Türk Cumhuriyetiilelebet muhafaza ve müdafaa etmektir.
Writing deneme.txt
Kaan Öztürk
April 11, 2018
Yazı dizimizin bu bölümünde, dosya okuma ve yazma yöntemlerinden bahsedeceğiz. Önce herhangi bir özel şekilde yapılanmamış olan düz metin dosyalarını işlemeyi göreceğiz. Ardından csv
modülüyle CSV biçiminde yapılanmış dosyaları okuyup yazmayı inceleyeceğiz. JSON, ZIP, PDF, Word, Excel, HTML dosyalarının işlenmesine kısaca değineceğiz. Son olarak, Python oturumunda yarattığımız nesneleri ikili (binary) formda dosyaya kaydetmemizi ve sonra dosyadan tekrar yüklememizi sağlayan pickle
modülünün kullanımını özetleyeceğiz.
Öncelikle, IPython sihirleriyle deneme.txt isimli bir dosya yaratalım (Jupyter kullanmıyorsanız aşağıdaki metni bir metin editörüne kopyalayıp deneme.txt ismiyle çalışma dizininize kaydedebilirsiniz).
%%writefile deneme.txt
Ey Türk Gençliği!
Birinci vazifen,
Türk istiklâlini, Türk Cumhuriyeti'ni,
ilelebet muhafaza ve müdafaa etmektir.
Writing deneme.txt
Bir dosyayı açmak için open()
fonksiyonunu kullanırız. En basit halinde open()
mevcut bir metin dosyasını okumak için açar ve bir dosya nesnesi döndürür.
Dosya nesnesinin read()
metodu dosya içeriğini tek bir dize halinde döndürür.
"Ey Türk Gençliği!\nBirinci vazifen, \nTürk istiklâlini, Türk Cumhuriyeti'ni, \nilelebet muhafaza ve müdafaa etmektir.\n"
Açılmış dosyalarla işimiz bittiğinde kapatmamız gerekir, yoksa bellekte birikip yer işgal edebilirler.
readlines()
metodu, satırlardan oluşan bir liste döndürür:
['Ey Türk Gençliği!\n',
'Birinci vazifen, \n',
"Türk istiklâlini, Türk Cumhuriyeti'ni, \n",
'ilelebet muhafaza ve müdafaa etmektir.\n']
Bir dosya nesnesi bir iteratördür; bütün dosyayı bir kerede belleğe yüklemez, ama talep geldikçe satırları birer birer verir. readline()
metodu dosyadaki mevcut satırı okumak için kullanılır. Her yeni readline()
çağrısı bir sonraki satırı getirir.
Dosya nesnesi bir iteratör olduğu için for
döngüsünde kullanılabilir. Bir dosyayı satır satır işlemek için şöyle bir döngü kurulur.
with ... as
Yukarıda, dosyayı open()
ile açtıktan sonra close()
metoduyla kapatmak gerektiğini söyledik. Bu basit bir kural olsa da, karmaşık programlar içinde gözden kaçabiliyor. Dosya açma/kapama işlemini daha düzenli hale getirmek için Python programcıları context manager denen bir yapı kullanırlar. Bir context manager oluşturmak için with ... as
komutu kullanılır.
Ey Türk Gençliği!
Birinci vazifen,
Türk istiklâlini, Türk Cumhuriyeti'ni,
ilelebet muhafaza ve müdafaa etmektir.
Context manager ayrı ve geniş bir konudur, ayrıntısı için Python belgelerine bakabilirsiniz. Bizim açımızdan önemli olan, burada with
bloku bitince dosyanın otomatik olarak kapatılmasıdır. Dosyanın kapanmış olduğunu, dosya nesnesinin closed
değişkeninin durumuyla kontrol edebiliriz.
Bir dosyaya yazmak için open()
fonksiyonunda "w"
(write) modunu kullanırız.
Bu komutla, mevcut dizinde deneme2.txt dosyası yoksa yaratılır, varsa mevcut içeriği silinip üstüne yeni veri yazılır. Açılan dosyaya bir dize yazmak için write()
metodu kullanılır.
Dosyayı açarak, veya %cat
sihirini kullanarak içeriğine bakabiliriz.
Aynısını bir context manager ile de yapabiliriz:
Dosyada mevcut bulunan verileri silmeden, yeni verilerin dosyanın altına eklenmesini istersek dosyayı "a"
(append) modunda açmalıyız.
Bir çok veri dosyasında veriler tablo halinde, her satırda bir kayıt ve her sütunda o kayda ait bir alan olacak şekilde düzenlenmişlerdir. Alanlar birbirlerinden boşlukla, virgülle, veya başka bir karakterle ayrılabilir. Bu tür bir dosya düzenine CSV (comma-separated values, virgülle ayrılmış değerler) adı verilir. CSV biçimindeki dosyaları okumak için yukarıda açıkladığımız genel yöntemleri kullanmak mümkünse de, Python’un csv
modülü işleri basitleştirir. Sözgelişi MS Excel ve benzeri bir hesap tablosunu CSV biçiminde kaydedip, verileri Python ile okuyabilirsiniz; veya Python’la üretilen verileri CSV dosyası olarak kaydedip hesap tablosu uygulamasıyla açabilirsiniz.
Önce bir örnek veri dosyası hazırlayalım.
%%writefile ornek.csv
"Potter, H",37,"Londra, İngiltere"
"Granger, H",36,"Sydney, Avustralya"
"Weasley, Bill",45,"Bükreş, Romanya"
Writing ornek.csv
Bu örnekte isim ve adres alanı değerlerinin tırnak içinde yazıldığına dikkat edin. Eğer tırnak kullanılmasaydı, alanları virgülle ayırma kuralı bize "Potter"
, "H"
, 37
, "Londra"
, "İngiltere"
gibi beş ayrı alan verirdi.
Bir CSV dosyasını açtıktan sonra, csv
modülündeki reader()
fonksiyonunu kullanarak onu satır satır okuyacak bir iteratör nesnesi yaratırız. Sonra bu iteratör nesnesi üzerinde bir döngüyle dosyayı tarayabiliriz.
['Potter, H', '37', 'Londra, İngiltere']
['Granger, H', '36', 'Sydney, Avustralya']
['Weasley, Bill', '45', 'Bükreş, Romanya']
Veya dosyamızda alan ayırıcı olarak boşluk karakteri, alan gruplama için bölü işareti (/
) kullanılmış olabilir. Bu durumda reader()
fonksiyonundaki delimiter
ve quotechar
parametrelerini değiştirerek dosyayı doğru şekilde alabiliriz.
%%writefile ornek2.csv
/Potter, H/ 37 /Londra, İngiltere/
/Granger, H/ 36 /Sydney, Avustralya/
/Weasley, Bill/ 45 /Bükreş, Romanya/
Writing ornek2.csv
with open("ornek2.csv") as f:
okur = csv.reader(f, delimiter=" ", quotechar="/")
for satır in okur:
print(satır)
['Potter, H', '37', 'Londra, İngiltere']
['Granger, H', '36', 'Sydney, Avustralya']
['Weasley, Bill', '45', 'Bükreş, Romanya']
Görüldüğü gibi, bir CSV dosyasında alan ayırma, gruplama, satır sonu karakterleri için farklı tercihler olabilir. Her bir tercih kümesine bir lehçe (dialect) adı veriliyor. csv.reader()
için varsayılan lehçe olan "excel"
, MS Excel ile üretilen CSV dosyalarını okumaya ayarlıdır. Ancak yukarıda gördüğümüz gibi bu tercihler kolaylıkla değiştirilebilir.
Eğer özel bir CSV biçimini sık sık kullanıyorsanız, o lehçeye özel bir Dialect
nesnesi oluşturup reader()
ile birlikte kullanabilirsiniz. Bunun ayrıntılarını Python belgelerinden öğrenebilirsiniz.
Elimizdeki verileri bir CSV dosyasına yazmak için önce csv
modülünün writer()
fonksiyonuyla bir yazıcı nesnesi yaratırız. Yazıcı nesnesi verilen veriyi kullanılan “lehçe”ye uygun şekilde bir dizeye dönüştürür ve dosyaya yazar. Yazılacak dosyayı open()
ile açarken newline=""
parametresi vermemiz gerekir.
Yazıcı nesnesinin writerow()
metodu yazılacak satırı bir liste olarak alır.
Dosyanın içeriğine bakarak doğru yazılıp yazılmadığını kontrol edelim
CSV dosyalarını veri analizi paketi pandas ile de okumak ve yazmak mümkündür. Pandas ile CSV okumak hem daha basittir, hem de csv
modülünde bulunmayan sözgelişi veri içindeki yorumları elemek, sadece istenen sütunları almak gibi ince ayarlara da imkan verir.
Pandas’ın read_csv()
fonksiyonu dosyanın içeriğini bir veri çerçevesi olarak okur; ardından bu veri çerçevesinden çeşitli satırlar veya sütunlar alınabilir. Pandas kullanımı bu notların kapsamı dışında olduğu için ayrıntıya girmiyorum.
Birçok dosya biçimi için Python’da özelleşmiş kütüphaneler vardır. Bunların bazılarına değinelim.
Birçok internet hizmeti API’si, sorgulama sonuçlarını JSON biçiminde bir dosya olarak verir (sözgelişi daha önce Foursquare, Weather Underground ve Star Wars API’lerini JSON verilerini incelemiştik). Python standart kütüphanesindeki json
modülü, JSON biçimli bir dosyayı okuyup bir Python sözlük veya listesine dönüştüren, ve Python nesnelerinden JSON biçimli bir dosya oluşturan fonksiyonları içerir.
Mockaroo sitesini kullanarak yalancı veri içeren küçük bir JSON dosyası üretelim.
%%writefile yalanci_veri.json
[{
"id": 1,
"first_name": "Fredia",
"last_name": "Waith",
"email": "fwaith0@tamu.edu"
}, {
"id": 2,
"first_name": "Rafaello",
"last_name": "Rowthorn",
"email": "rrowthorn1@stanford.edu"
}, {
"id": 3,
"first_name": "Harriette",
"last_name": "Patters",
"email": "hpatters2@samsung.com"
}]
Writing yalanci_veri.json
Şimdi bu dosyayı açıp, içeriğini yorumlayalım ve bir Python nesnesine aktaralım.
Bu işlem sonucunda bir sözlükler listesi elde etmiş oluruz. Bilindik indeksleme işlemleriyle tek tek elemanlara ulaşabiliriz.
Şimdi JSON dosyası yazmayı görelim. Elimizdeki veriye bir satır daha ekleyelim ve nesnenin yeni halini json.dump()
ile dosyaya yazalım.
Dosyanın içeriğine bakarak beklediğimiz şekilde yazıldığını görebiliyoruz.
[{"id": 1, "first_name": "Fredia", "last_name": "Waith", "email": "fwaith0@tamu.edu"}, {"id": 2, "first_name": "Rafaello", "last_name": "Rowthorn", "email": "rrowthorn1@stanford.edu"}, {"id": 3, "first_name": "Harriette", "last_name": "Patters", "email": "hpatters2@samsung.com"}, {"id": 4, "first_name": "Giffer", "last_name": "Dur", "email": "gdur2@cnbc.com"}]
HTML dosyaları zaten düz metinden oluştuğu için onları okumakta teknik bir zorluk yok. HTML işlemede asıl istenen şey parsing, yani çeşitli HTML elemanlarına erişebilmektir. Söz gelişi, bir HTML’deki bağlantıları almak, tablo veriyi okumak gibi işlemler yapmamız gerekebilir. Bu tür işlemler bu yazı dizisinin kapsamını aşıyor. İlgilenenler, en çok kullanılan araçlardan biri olan Beautiful Soup modülüyle denemeler yapabilirler.
MS Excel dosyalarını CSV olarak kaydederseniz CSV okuma/yazma kısmındaki yöntemleri kullanabilirsiniz. Bunu istemiyorsanız, veya tablodaki verileriniz bu işleme uygun değilse, veya birden fazla yapraktan oluşuyorsa, Excel dosyasını doğrudan açmak için xlrd modülünü kullanabilirsiniz.
Daha geniş özelliklere sahip bir paket olan pyexcel ile hem okuma hem de yazmayı daha kolay işlemlerle yapabilirsiniz.
Pandas paketinin read_excel()
fonksiyonu ile bir Excel dosyasını doğrudan okuyarak bir veri çerçevesi haline getirebilirsiniz. Kullanımına bir örnek görmek için “Groupby” yazımıza bakabilirsiniz. Word
MS Word belgelerinin içinden metin almak, belge yaratmak ve varolan belgeye içerik eklemek için python-docx modülü kullanılabilir. Örnekler için Al Sweigart’ın Automate The Boring Stuff with Python kitabına bakabilirsiniz.
PDF dosyalarından bilgi almak, PDF dosyası yaratmak, mevcut dosyada değişiklik yapmak gibi işler için pyPDF2 modülünü kullanabilirsiniz. Sweigart’ın Automate The Boring Stuff with Python [kitabında] (https://automatetheboringstuff.com/chapter13/) bu modülün kullanımına dair açıklayıcı örnekler bulabilirsiniz.
Python standart kütüphanesindeki zipfile modülü, ZIP formatında sıkıştırma ve açma fonksiyonları sağlar. Basit bir örnek olarak, yukarıda kullandığımız deneme.txt ve yalanci_veri.json dosyalarını sıkıştırarak bir arşiv dosyası oluşturalım.
Mevcut bir arşive bir dosya eklemek istiyorsak, ZipFile()
fonksiyonunun açılma modunu "w"
yerine "a"
yaparız.
ZipFile()
fonksiyonu, yukarıda gördüğümüz open()
gibi çalışır. Arşivi açmak için ZipFile()
fonksiyonunu okuma modunda kullanırız, ve arşiv dosyası nesnesine ait open()
metoduyla dosyayı açarız. Açılan dosyanın içeriği read()
, readline()
veya readlines()
metodlarıyla okunabilir. Bu metodlar kodlanmış dizeler döndürdüğü için decode()
dize metoduyla Unicode’a çevrilmelidir.
with zipfile.ZipFile('arsiv.zip') as z:
with z.open('deneme.txt') as f:
print(f.read().decode("utf-8"))
Ey Türk Gençliği!
Birinci vazifen,
Türk istiklâlini, Türk Cumhuriyeti'ni,
ilelebet muhafaza ve müdafaa etmektir.
Bir ZIP arşivindeki bir dosyayı açarak diske kaydetmek için extract()
, arşivdeki bütün dosyaları açmak için extractall()
fonksiyonları kullanabiliriz.
Bir oturumda hazırladığınız değişkenleri, oturumu kapattığınızda kaybetmemek isterseniz bunları ikili (binary) bir veri yapısı haline getirip diske kaydetmeniz gerekir. Bu işi standart kütüphanedeki pickle modülü ile yapabilirsiniz. Neredeyse bütün Python nesnelerini (kendi tanımladığımız nesne sınıfları dahil) dosyaya kaydetmeniz ve sonra tekrar okumanız mümkündür. Bu işleme serialization adı verilir.
Birkaç değişken tanımlayalım.
Verileri kaydetmek istediğimiz dosyayı ikili yazma modunda açalım ve pickle modülündeki dump()
fonksiyonuyla değişkenleri dosyaya ekleyelim.
Değişkenleri dosyadan okumak için load()
fonksiyonunu kullanırız. Nesneler dosyaya kondukları sırayla geri alınırlar. Değişkenlerin orijinal adını kullanmamız gerekmez.
with open("data.p", "rb") as f:
y = pickle.load(f)
print(y)
J = pickle.load(f)
print(J)
F = pickle.load(f)
print(F)
G = pickle.load(f)
print(G(y))
3.14159
[1, 3, 2, 5, 4]
{'abc': 123, 'def': 456}
9.869587728099999
Bazı nesneler pickle ile kaydedilemezler; ağ bağlantıları, veri tabanı bağlantıları, açık dosya nesneleri gibi.
Dikkat: pickle işlemleri herhangi bir emniyet tedbiri içermez. Pickle dosyasının içindeki nesne load()
ile doğrudan doğruya çalıştırılır. Bu nesnenin içinde kötü amaçlı bir kod parçası varsa sisteminize zarar gelebilir. Bu yüzden bilmediğiniz bir yerden gelen pickle dosyalarını açmayın.