1 पॉइंट द्वारा GN⁺ 2024-08-23 | 1 टिप्पणियां | WhatsApp पर शेयर करें

Python का प्रीप्रोसेसर

  • यह दावा सही नहीं है कि Python में प्रीप्रोसेसर नहीं होता
  • Python में एक बहुत शक्तिशाली प्रीप्रोसेसर होता है

Python source code encoding

  • PEP-0263 की बदौलत source code encoding को परिभाषित किया जा सकता है
  • पहली दो लाइनों में magic comment जोड़कर encoding सेट की जा सकती है
  • उदाहरण: # coding=utf8, # -*- coding: utf8 -*-, # vim: set fileencoding=utf8 :

path configuration files (.pth)

  • जब Python interpreter -S option के बिना शुरू होता है, तो वह site package को अपने आप load करता है
  • site-packages folder में .pth file जोड़कर module search path को बढ़ाया जा सकता है
  • .pth file में import से शुरू होने वाली lines execute की जाती हैं
  • इससे Python interpreter initialization के समय मनचाहा code चलाया जा सकता है

custom codec की परिभाषा

  • Python interpreter की दो ज़रूरतें पूरी करनी होती हैं:
    • decode(data: bytes) -> tuple[str, int] function
    • incremental decoder class
  • असली decoding करने के लिए codecs.utf_8_decode का उपयोग करें, और result string को प्रीप्रोसेसर तक पहुँचाएँ
  • exception को पकड़कर print करना और फिर दोबारा raise करना बेहतर है

incremental decoder उपलब्ध कराना

  • codecs.BufferedIncrementalDecoder inherit करके incremental decoder implement करें
  • buffer में data इकट्ठा करें और final decode call पर पूरी file को preprocess करें

Python का विस्तार

  • Python की standard library का उपयोग करके Python का विस्तार करना अपेक्षाकृत आसान है
  • tokenize module का उपयोग करके file की token stream बदली जा सकती है या ast module का उपयोग करके abstract syntax tree को बदला जा सकता है
unary increment और decrement
  • Python में unary increment और decrement operator नहीं हैं
  • x++, x-- valid नहीं हैं
  • ++x, --x valid हैं, लेकिन उनका अर्थ अलग होता है
  • unary increment और decrement expressions को Python expressions में बदला जा सकता है
उदाहरण
  • input file 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")
    
  • बदली हुई file:
    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")
    

braces का उपयोग करने वाला Python (Bython)

  • Python की indentation के बजाय braces का उपयोग करके scope तय किया जा सकता है
  • token stream को बदलने के लिए tokenize.generate_tokens का उपयोग करें
उदाहरण
  • input file 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()})
    }
    
  • बदली हुई file:
    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()})
    

दूसरी भाषाओं की व्याख्या

  • Python interpreter को दूसरी भाषाओं की व्याख्या करने के लिए भी इस्तेमाल किया जा सकता है
  • उदाहरण: C, C++, TOML
उदाहरण
  • C++ file test.cpp:
    #define CODEC "coding:magic.cpp"
    #include <cstdio>
    int main() {
      puts("Hello World");
    }
    
  • बदली हुई file:
    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()
    

data validation

  • TOML format के data को JSON schema का उपयोग करके validate किया जा सकता है
  • असली validation के लिए jsonschema का उपयोग करें
उदाहरण
  • schema file 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"]
        }
      }
    }
    
  • valid data file data_valid.toml:
    # coding: magic.toml
    name = "John Doe"
    age = 42
    scores = [40, 20, 80, 90]
    [address]
    street = "Grove St. 4"
    postcode = 19201
    
  • invalid data file data_invalid.toml:
    # coding: magic.toml
    name = "John Doe"
    age = 42
    scores = [40, "20", 80, 90]
    [address]
    street = "Grove St. 4"
    postcode = 19201
    

निष्कर्ष

  • custom codec और path configuration file का उपयोग करके Python interpreter के व्यवहार को काफी हद तक बदला जा सकता है
  • उदाहरण के तौर पर pythonql, future-typing, future-fstrings, future-annotations आदि हैं
  • magic_codec का उपयोग करके अपना प्रीप्रोसेसर आसानी से प्रयोगात्मक रूप से बनाया जा सकता है

GN⁺ का सार

  • Python के प्रीप्रोसेसर का उपयोग करके अलग-अलग language extension और data validation किए जा सकते हैं
  • यह समझाया गया है कि custom codec के माध्यम से Python interpreter के व्यवहार को कैसे बदला जा सकता है
  • यह लेख Python developers के लिए उपयोगी tools और techniques प्रदान करता है
  • मिलती-जुलती functionality वाले projects में pythonql, future-typing आदि शामिल हैं

1 टिप्पणियां

 
GN⁺ 2024-08-23
Hacker News राय
  • from __future__ import braces का syntax error message 2001 से cpython में hardcoded है

    • इसे Jeremy Hylton ने लिखा था, जो फिलहाल Google में AI search quality के लिए principal engineer के रूप में काम कर रहे हैं
    • यह देखकर हैरानी होती है कि 24 साल में एक व्यक्ति का करियर एक खास syntax प्रतिबंध को यादगार बनाने से शुरू होकर ऐसे search system पर काम करने तक पहुँचा, जिसे समर्पित syntax की ज़रूरत नहीं है
  • import-hooks का उपयोग करके किसी को निकालने के रचनात्मक तरीकों के बारे में सोचा था, लेकिन यह अफसोस रहा कि codec regex "μtf8" जैसी चीज़ इस्तेमाल नहीं करने देता

    • इसलिए import hooks, preprocessors, sys.settrace का इस्तेमाल करके हर function को उससे पहले कॉल किए गए function से monkey patch करना होगा, और हर 17 मिनट में stdout और stderr को आपस में बदलना होगा
  • कोई वजह है कि python preprocessor hooks expose नहीं करता, और मुझे लगता है कि समझदार वयस्कों को इससे बचना चाहिए

    • लेकिन समझदार वयस्कों से अलग, मैं मज़े के लिए इसे करना चाहता हूँ
  • preprocessor ज़्यादा सुविधाजनक और उपयोगी है

    • मैंने ast module का इस्तेमाल करके code rewrite किया, उसे exec से चलाया, और फिर exit() insert करके hack किया
    • सभी dicts के ordered होने से पहले, मैंने ast rewriting feature का उपयोग काफ़ी काम की चीज़ के रूप में किया था
  • मुझे python की flexibility बहुत पसंद है

    • सबसे cursed काम जो मैंने किया, वह strings को in-place mutate करना था, और मैंने mmap का दुरुपयोग करके script को खुद को modify करने पर मजबूर किया
    • अब मैं एक Lisp interpreter लिखना चाहता हूँ
  • pyxl का उपयोग करने का सबसे अच्छा उदाहरण JSX से प्रेरित है

    • # coding: pyxl का इस्तेमाल करके HTML code लिखा जा सकता है
  • सोचता हूँ कि Python 2 से 3 में transition को क्या बेहतर ढंग से संभाला जा सकता था

    • # coding: six.python2 Python2 code को Python3 में valid बना सकता है, और # coding: six.python3 Python3 code को Python2 में runnable बनाने के लिए adjust कर सकता है
  • अच्छा लगा कि तुम्हें यह idea पसंद आया, जल्द ही और सामग्री आने वाली है

  • बहुत समय बाद किसी पूरी तरह नए idea पर हैरानी महसूस हुई

  • अगर Python में inline code generation चाहिए, तो Ned Batchelder का cog इस्तेमाल कर सकते हैं

  • सोच रहा हूँ कि इस coding hook strategy से लाई गई dependencies को pip freeze या uv detect करते हैं या नहीं

    • अगर नहीं, तो मज़े से इस्तेमाल करो। शायद library को rewrite करना ज़्यादा आसान होगा (अगर ऐसा एक pitfall है, तो और भी होने की पूरी संभावना है)