Python'un Ön İşlemcisi
(pydong.org)Python'un Ön İşlemcisi
- Python'da ön işlemci olmadığı iddiası doğru değil
- Python'ın çok güçlü bir ön işlemcisi var
Python kaynak kodu kodlaması
- PEP-0263 sayesinde kaynak kodu kodlaması tanımlanabilir
- İlk iki satıra magic comment eklenerek kodlama ayarlanabilir
- Örnekler:
# coding=utf8,# -*- coding: utf8 -*-,# vim: set fileencoding=utf8 :
Yol yapılandırma dosyaları (.pth)
- Python yorumlayıcısı
-Sseçeneği olmadan başlatıldığındasitepaketini otomatik olarak yükler - Modül arama yolunu genişletmek için
site-packagesklasörüne.pthdosyaları eklenebilir .pthdosyasındakiimportile başlayan satırlar çalıştırılır- Bu sayede Python yorumlayıcısı başlatılırken keyfi kod çalıştırılabilir
Özel codec tanımı
- Python yorumlayıcısının karşılamasını beklediği iki gereksinim vardır:
decode(data: bytes) -> tuple[str, int]fonksiyonu- artımlı decoder sınıfı
- Gerçek decode işlemini yapmak için
codecs.utf_8_decodekullanılır ve sonuç dizesi ön işlemciye aktarılır - İstisnaları yakalayıp yazdırmak ve sonra yeniden fırlatmak iyi bir yaklaşımdır
Artımlı decoder sağlama
- Artımlı decoder,
codecs.BufferedIncrementalDecodersınıfından türetilerek uygulanabilir - Veriler tamponda toplanır ve son decode çağrısında tüm dosya ön işlemden geçirilir
Python'ı genişletmek
- Python'ın standart kütüphanesini kullanarak Python'ı genişletmek nispeten kolaydır
- Dosyanın token akışını değiştirmek için
tokenizemodülü, soyut sözdizim ağacını değiştirmek içinastmodülü kullanılabilir
Tekli artırma ve azaltma
- Python'da tekli artırma ve azaltma operatörleri yoktur
x++,x--geçerli değildir++x,--xgeçerlidir ama farklı anlam taşır- Tekli artırma ve azaltma ifadeleri Python ifadelerine dönüştürülebilir
Örnek
- Girdi dosyası
incdec.py:# coding: magic.incdec i = 6 assert i-- == 6 assert i == 5 assert ++i == 6 assert --i == 5 assert i++ == 5 assert i == 6 assert (++i, 'i++') == (7, 'i++') print("PASSED") - Dönüştürülmüş dosya:
i = 6 assert ((i, i := i - 1)[0]) == 6 assert i == 5 assert ((i, i := i + 1)[1]) == 6 assert ((i, i := i - 1)[1]) == 5 assert ((i, i := i + 1)[0]) == 5 assert i == 6 assert (((i, i := i + 1)[1]), 'i++') == (7, 'i++') print("PASSED")
Süslü parantez kullanan Python (Bython)
- Kapsam, Python'ın girintisi yerine süslü parantezlerle belirtilebilir
- Token akışını değiştirmek için
tokenize.generate_tokenskullanılabilir
Örnek
- Girdi dosyası
test.by:# coding: magic.braces def print_message(num_of_times) { for i in range(num_of_times) { print("braces ftw") } print({'x': 3}) } x = { 'foo': 42, 'bar': 5 } if __name__ == "__main__" { print_message(2) print({k: v for k, v in x.items()}) } - Dönüştürülmüş dosya:
def print_message(num_of_times): for i in range(num_of_times): print("braces ftw") print({'x': 3}) x = { 'foo': 42, 'bar': 5 } if __name__ == "__main__": print_message(2) print({k: v for k, v in x.items()})
Başka dilleri yorumlama
- Python yorumlayıcısının başka dilleri yorumlaması sağlanabilir
- Örneğin: C, C++, TOML
Örnek
- C++ dosyası
test.cpp:#define CODEC "coding:magic.cpp" #include <cstdio> int main() { puts("Hello World"); } - Dönüştürülmüş dosya:
import cppyy cppyy.cppdef(r""" #define CODEC "coding:magic.cpp" #include <cstdio> int main() { puts("Hello World"); } """) from cppyy.gbl import main if __name__ == "__main__": main()
Veri doğrulama
- TOML biçimindeki veriler JSON şeması kullanılarak doğrulanabilir
- Gerçek doğrulama işlemi için
jsonschemakullanılır
Örnek
- Şema dosyası
schema.json:{ "type": "object", "properties": { "name": {"type": "string"}, "age": {"type": "number"}, "scores": { "type": "array", "items": {"type": "number"} }, "address": {"$ref": "#/$defs/address"} }, "required": ["name"], "$defs": { "address": { "type": "object", "properties": { "street": {"type": "string"}, "postcode": {"type": "number"} }, "required": ["street"] } } } - Geçerli veri dosyası
data_valid.toml:# coding: magic.toml name = "John Doe" age = 42 scores = [40, 20, 80, 90] [address] street = "Grove St. 4" postcode = 19201 - Geçersiz veri dosyası
data_invalid.toml:# coding: magic.toml name = "John Doe" age = 42 scores = [40, "20", 80, 90] [address] street = "Grove St. 4" postcode = 19201
Sonuç
- Özel codec'ler ve yol yapılandırma dosyaları kullanılarak Python yorumlayıcısının davranışı büyük ölçüde değiştirilebilir
- Örnekler arasında
pythonql,future-typing,future-fstrings,future-annotationsyer alıyor - Kendi ön işlemcinizi kolayca denemek için
magic_codeckullanılabilir
GN⁺ Özeti
- Python'un ön işlemcisi kullanılarak çeşitli dil genişletmeleri ve veri doğrulama işlemleri yapılabilir
- Özel codec'ler aracılığıyla Python yorumlayıcısının davranışının nasıl değiştirilebileceği açıklanıyor
- Bu yazı, Python geliştiricileri için yararlı araçlar ve teknikler sunuyor
- Benzer işlevlere sahip projeler arasında
pythonql,future-typingve diğerleri bulunuyor
1 yorum
Hacker News yorumu
from __future__ import bracessözdizimi hatası mesajı 2001'den beri cpython içinde hardcode edilmiş durumdaimport-hooks kullanarak yaratıcı bir işten çıkarılma yöntemi düşündüm, ama codec regex'in
"μtf8"gibi bir şeyi kullanmayı engellemesi üzücüsys.settracekullanarak tüm fonksiyonları daha önce çağrılmış fonksiyonlarla monkey patch'lemek ve stdout ile stderr'yi her 17 dakikada bir değiştirmek gibi bir yöntem kullanmak gerekiyorPython'ın preprocessor hook'larını dışa açmamasının bir nedeni var ve bence makul yetişkinlerin bundan kaçınması gerekir
preprocessor'ler daha kullanışlı ve faydalı
astmodülünü kullanarak kodu yeniden yazıpexecile çalıştırdıktan sonraexit()ekleyen bir hack yaptımastyeniden yazım özelliğini faydalı olacak şekilde kullanıyordumPython'ın esnekliğini seviyorum
mmap'i suistimal ederek script'in kendisini dönüştürmesini sağlamıştımpyxlile ilgili en iyi kullanım örneği JSX'ten ilham alıyor# coding: pyxlkullanarak HTML kodu yazabiliyorsunuzPython 2'den 3'e geçişin daha iyi yönetilip yönetilemeyeceğini merak ediyorum
# coding: six.python2, Python2 kodunu Python3'te geçerli hale getirebilir ve# coding: six.python3, Python3 kodunu Python2'de çalıştırılabilir olacak şekilde uyarlayabilirBu fikri beğenmenize sevindim, yakında daha fazlası gelecek
Uzun zamandır ilk kez tamamen yeni bir fikir karşısında şaşkınlık hissettim
Python'da satır içi kod üretimi istiyorsanız, Ned Batchelder'in cog aracını kullanabilirsiniz
Bu coding hook stratejisiyle eklenen bağımlılıkların
pip freezeveya uv tarafından tespit edilip edilmediğini merak ediyorum