İleri Python Geliştirme Kursu
Bölüm
>
Seviye
Serileştirme Modülleri
Struct Modülü
Amaç
Yeni tarla için son veri dökümünü struct modülü kullanarak ayarlayın.
Yolun sonunda, zaten inşa edilmiş ve mahsulleri dikilmiş olan yeni tarlayı yöneten bir servis istasyonu bulunuyor. Burada, zaten dikilmiş mahsullerin verilerini ve tarlanın öngörülen üretimini inceleyip işliyor olacağız. Bu bölümdeki diğer seviyelerde olduğu gibi, veri serileştirme ve seriden çıkarma işlemleri üzerinde çalışacağız; son olarak struct modülü tanıtılıyor.
Struct modülü, veriyi ikili (binary) formatta paketleyen bir dizi serileştirme işlevi sunar; üzerinde çalıştığımız diğer modüllerin aksine, veriyi hem serileştirirken hem de sonrasında seriden çıkarırken nasıl yapılandıracağımıza dair daha fazla kontrole sahip olmanızı sağlar, bu da onu diğer modüllerden daha esnek kılar. Aşağıdaki verileri işlemek için kullanacağımız işlevlere erişmek üzere import struct ifadesini kullanın:
struct.calcsize(): Belirli bir format dizesinin kaç bayt paketlediğini belirler, tek bir (1) argüman alır; bu argüman bayt boyutunu kontrol etmek istediğiniz formattır. Kullanacağımız formatlar şunlardır:- integer:
'i'ile temsil edilir; tam sayı olarak temsil edilen veriler içindir - float:
'f'ile temsil edilir; ondalık sayı olarak temsil edilen veriler içindir - double:
'd'ile temsil edilir; float formatının yeterli olmadığı daha karmaşık ondalık sayılar içindir
- integer:
struct.pack(): Veriyi ikili (binary) olarak, seçtiğiniz bir formatta serileştirir. Kullanmak istediğiniz formatı ve serileştirmek istediğiniz değerleri içeren iki (2) veya daha fazla argüman alır. Formatlar daha önce belirtildiği gibidir ve eklediğiniz argüman sayısına karşılık gelen format karakterlerini eklemelisiniz.struct.unpack(): Paketlenmiş ikili veriyi seriden çıkarır, iki (2) argüman alır: ilki verinin serileştirildiği formatla uyumlu olması gereken formattır, ikincisi ise serileştirilmiş veridir.struct.iter_unpack(): Paketlenmiş ikili veriyi seriden çıkarır;struct.unpack()ile aynı şekilde çalışır ancak bir döngü kullanarak her veri bloğunu ayrı ayrı iterasyona tabi tutar.struct.pack_into():struct.pack()işlevinin gelişmiş bir versiyonudur; dört (4) argüman alır: kullanmak istediğiniz format, veriyi koymak istediğiniz tampon (buffer), verinin tampon içinde yer almasını istediğiniz pozisyon ve paketlemek istediğiniz veri.struct.unpack_from():struct.unpack()işlevinin gelişmiş bir versiyonudur; üç (3) argüman alır: kullanmak istediğiniz format, seriden çıkarılacak verinin bulunduğu tampon ve seriden çıkarma işlemini tampon içinde başlatmak istediğiniz konum. Bu sayede verinin belirli bölümlerini seriden çıkarabilirsiniz.
Servis istasyonunda ışıklı X işaretine gidin ve masaya dönün, integer, float ve double adlarında üç (3) değişken oluşturun. Bu değişkenleri kullanarak struct.calcsize() işleviyle her formatın bayt cinsinden boyutunu doğrulayacağız. integer değişkeni için işlevi 'i' argümanıyla, float değişkeni için 'f' argümanıyla ve son olarak double değişkeni için 'd' argümanıyla kullanın. Örneğin: integer = struct.calcsize('i'). Üç (3) değişkeni önceden yazılmış write() işlevine ekleyin.
Altın X işaretine doğru yürüyün ve yeni tarla hakkında veri toplamak için read() işlevini kullanın; ileride kullanmak üzere Resources, Size ve Estimate veri noktalarını ve formatlarını not edin. Bunları not ettikten sonra mavi halının üzerindeki ışıklı X işaretine gidin ve blue_data adında bir değişken oluşturun.
blue_data değişkenine, daha önce not ettiğiniz formatı ve değerleri argüman olarak belirterek struct.pack() işlevinin döndürdüğü değeri atayın. Formatı yazarken format türlerini tek bir birim halinde “paketlemelisiniz”. Örneğin, integer formatı daha önce belirtilen gibi 'i' ile etiketlenir; üç adet integer veri ekliyorsanız, 'iii' olarak yazarsınız. Benzer şekilde, bir integer, bir float ve bir double ekliyorsanız 'ifd' olarak yazılır. Verileri eklerken her birini ayrı ayrı argüman olarak yazarsınız. İşte genel bir örnek:
data_1 = 8 # is an integer data_2 = 2.25 # is a float data_3 = 900.702938103 # is a double blue_data = struct.pack('ifd', data_1, data_2, data_3)
struct.pack() işlevi oldukça esneklik sağlar; veriyi nasıl formatlamak istediğinizi belirlemenize ve aynı anda birden fazla veri noktasını isteğinize göre serileştirmenize olanak tanır. Önceki read() ile okunan verileri yukarıdaki örneği temel alarak ekleyin. Paketlenmiş veriyi görüntülemek için blue_data'yı argüman olarak kullanarak display() işlevini çağırın.
Mavi halının üzerindeki karanlık X işaretine gidin ve terminale dönün; blue_unpack adında bir değişken oluşturun ve aynı formatı ve blue_data değişkenini argüman olarak ekleyerek struct.unpack() işlevinin döndürdüğü değeri atayın. Format, struct.pack() işleviyle yazıldığıyla aynı şekilde yazılır; böylece veriyi ilk serileştirdiğiniz biçimde seriden çıkarabilirsiniz. Önceden paketlediğiniz veriyi doğrulamak için blue_unpack argümanıyla write() işlevini kullanın.
Aynı konumda, struct.iter_unpack() işlevini de kullanacağız; bu işlev struct.unpack() ile tamamen aynı argümanları alır ancak bir for döngüsü şeklinde kullanılır; bu bize veriyi tamamını yazmak yerine yineleme yoluyla işlemeyi sağlar. İşlev şu şekilde kodlanır:
for values in struct.iter_unpack(-insert value-, -insert value-): player.speak(values)
Değerleri görüntülemek için speak() işlevini kullanacağız; struct.iter_unpack() işlevindeki eksik argümanlara, kullanım açısından aynı işlevin bir varyasyonu oldukları için struct.unpack() ile önce kullandığınız argümanları ekleyin.
Kırmızı halının üzerindeki altın X işaretine gidin ve masaya dönerek mahsul miktarlarını gözden geçirmek için read() işlevini kullanın. Tüm miktarları ve her mahsul için formatı not edin. Kırmızı halının üzerindeki ışıklı X işaretine gidin ve buffer adında bir nesne oluşturun; değer olarak bytearray(16) atayın. Bu, içine veri yerleştirmeden önce erişebileceğimiz bir byte koleksiyonudur; bizim için verileri manuel olarak saklayabileceğiniz bir veri bankası gibi çalışır. Argüman olarak verilen 16 sayısı, buffer nesnesine kaç bayt depolayabileceğinizi belirtir.
Oluşturduğunuz buffer nesnesini doldurmak için struct.pack_into() işlevini kullanın. İşlevin döndürdüğü değeri saklamak için ayrı bir değişken oluşturmanıza gerek yoktur; işlev değerleri doğrudan buffer nesnesine ekleyecektir. Daha önce not ettiğiniz her bir değer için bu işlevi kullanacak ve argümanlarını bu değerlere göre dolduracaksınız.
Örneğin, sağlanan ilk mahsul değeri için size formatı, byte konumu ve miktarı verilecektir. İlk argüman olarak formatı, ikinci argüman olarak byte'ları serileştirmek istediğiniz yeri (bu durumda buffer) ekleyin. Üçüncü argüman olarak değeri buffer içine eklemek istediğiniz pozisyonu belirtin; formatın kaç bayt kullanacağını hesaba katın, daha önce dolu olmayan byte konumlarını kullanarak veri paketlediğinizden emin olun. Son olarak, serileştirmek ve buffer nesnesine paketlemek istediğiniz değeri ekleyin.
struct.pack_into('i', buffer, 0, 82)
Daha önce belirtildiği gibi buffer nesnesi 16 bayta sahiptir. Yukarıdaki örnekte integer formatı 4 bayt kullanır ve pozisyon 0'a eklenir. Bu, veri buffer içine eklendiğinde, 0-3 pozisyonlarının sağlanan değer (bu örnekte 82) ile dolu olduğu ve geriye yalnızca 12 bayt boş alan kaldığı anlamına gelir. Daha önce okuduğunuz ve not ettiğiniz tüm mahsul veri noktaları için (toplamda üç (3) adet) aynı işlemi yapın. Serileştirilmiş veriyi görüntülemek için display() işlevine buffer'ı argüman olarak ekleyin.
Kırmızı halının üzerindeki karanlık X işaretine gidin ve terminale dönün; burada içeriği doğrulamak ve doğru depolamayı sağlamak için verileri seriden çıkaracağız. lettuce, carrots ve melons adlarında üç değişken oluşturun; her veri noktasının verisini ayrı ayrı seriden çıkaracağız. Her değişken için struct.unpack_from() işlevinin döndürdüğü değeri saklayın ve argümanları, veriyi paketlemek için not ettiğiniz aynı verilerle belirleyin. İlk argüman formatı, ikinci argüman seriden çıkarılacak verinin bulunduğu buffer nesnesini ve son argüman buffer içinden seriden çıkarma işlemini başlatmak istediğiniz pozisyonu belirtir. Örneğin:
lettuce = struct.unpack_from('i', buffer, 0)
Bu veri, önceki paketleme örneğine karşılık gelen verinin seriden çıkarılmasıdır; diğer iki değişken için de aynı işlemi yapın ve lettuce, carrots ile melons değişkenlerini önceden yazılmış write() işlevine ekleyerek bölümü tamamlayın.