Performance in Python

Simple performance in Python can be measured by the profile module using a command like,

$ python3 -m profile <script.py> {{args to script.py}}

Measuring performance of a simple iteration of Tamil spell checker shows,

python3 -m profile demo.py 
u'இன்பம்',
u'ஆப்பம்',
u'இன்னம்',
u'இன்பன்',
u'அற்பம்',
u'அப்பம்',
u'அற்றம்',
u'அற்கம்',
u'அக்கம்',
u'அட்டம்',
u'அம்மம்',
u'அற்பர்',
u'அப்பன்',
u'அப்பர்',
u'அப்பல்',
u'அம்பர்',
u'அம்பல்',
u'அன்னம்',
u'அன்னன்',
u'அன்னல்',
u'அன்பன்',
L = 21
         3192524 function calls (2736876 primitive calls) in 32.678 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
       39    0.002    0.000    0.022    0.001 :0(__build_class__)
        2    0.000    0.000    0.000    0.000 :0(__contains__)
     17/4    0.000    0.000    0.144    0.036 :0(__import__)
        2    0.000    0.000    0.000    0.000 :0(__new__)
       35    0.000    0.000    0.000    0.000 :0(_fix_co_filename)
        1    0.000    0.000    0.000    0.000 :0(_getframe)
      253    0.001    0.000    0.001    0.000 :0(acquire_lock)
        1    0.000    0.000    0.000    0.000 :0(add)
       94    0.000    0.000    0.000    0.000 :0(allocate_lock)
       44    0.001    0.000    0.002    0.000 :0(any)
   519988    2.090    0.000    2.090    0.000 :0(append)
       11    0.000    0.000    0.000    0.000 :0(bit_length)
        1    0.000    0.000    0.000    0.000 :0(callable)
        4    0.000    0.000    0.000    0.000 :0(cast)
   197036    0.815    0.000    0.815    0.000 :0(chr)
        1    0.000    0.000    0.000    0.000 :0(close)
        1    0.000    0.000    0.000    0.000 :0(cmp_to_key)
        3    0.000    0.000    0.000    0.000 :0(compile)
        1    0.000    0.000    0.000    0.000 :0(create_builtin)
        8    0.005    0.001    0.005    0.001 :0(create_dynamic)
        1    0.000    0.000    0.000    0.000 :0(dir)
       51    0.000    0.000    0.000    0.000 :0(endswith)
     37/1    0.001    0.000   32.675   32.675 :0(exec)
        1    0.000    0.000    0.000    0.000 :0(exec_builtin)
        8    0.000    0.000    0.000    0.000 :0(exec_dynamic)
        1    0.000    0.000    0.000    0.000 :0(exp)
       32    0.000    0.000    0.001    0.000 :0(extend)
       32    0.000    0.000    0.000    0.000 :0(find)
       17    0.000    0.000    0.000    0.000 :0(format)
       70    0.000    0.000    0.000    0.000 :0(from_bytes)
      117    0.001    0.000    0.001    0.000 :0(fspath)
   412207    1.985    0.000    1.985    0.000 :0(get)
      146    0.001    0.000    0.001    0.000 :0(get_ident)
      274    0.001    0.000    0.001    0.000 :0(getattr)
       36    0.001    0.000    0.001    0.000 :0(getcwd)
      168    0.001    0.000    0.001    0.000 :0(getlower)
       14    0.000    0.000    0.000    0.000 :0(globals)
      270    0.001    0.000    0.001    0.000 :0(hasattr)
        1    0.000    0.000    0.000    0.000 :0(index)
       20    0.000    0.000    0.000    0.000 :0(is_builtin)
       44    0.000    0.000    0.000    0.000 :0(is_frozen)
        6    0.000    0.000    0.000    0.000 :0(isidentifier)
      296    0.001    0.000    0.001    0.000 :0(isinstance)
        8    0.000    0.000    0.000    0.000 :0(items)
    64438    0.311    0.000    0.311    0.000 :0(join)
   172718    0.760    0.000    0.760    0.000 :0(keys)
129971/129966    0.664    0.000    0.664    0.000 :0(len)
        5    0.001    0.000    0.001    0.000 :0(listdir)
       35    0.010    0.000    0.010    0.000 :0(loads)
        2    0.000    0.000    0.000    0.000 :0(log)
        1    0.000    0.000    0.000    0.000 :0(lookup)
      101    0.000    0.000    0.000    0.000 :0(lower)
      102    0.000    0.000    0.000    0.000 :0(match)
        4    0.000    0.000    0.000    0.000 :0(max)
       39    0.000    0.000    0.000    0.000 :0(min)
        1    0.000    0.000    0.000    0.000 :0(open)
        1    0.000    0.000    0.000    0.000 :0(openssl_md5)
        1    0.000    0.000    0.000    0.000 :0(openssl_sha1)
        1    0.000    0.000    0.000    0.000 :0(openssl_sha224)
        1    0.000    0.000    0.000    0.000 :0(openssl_sha256)
        1    0.000    0.000    0.000    0.000 :0(openssl_sha384)
        1    0.000    0.000    0.000    0.000 :0(openssl_sha512)
    99429    0.397    0.000    0.397    0.000 :0(ord)
   172717    0.753    0.000    0.753    0.000 :0(pop)
       22    0.001    0.000    0.001    0.000 :0(print)
       37    0.002    0.000    0.002    0.000 :0(read)
      253    0.001    0.000    0.001    0.000 :0(release_lock)
        1    0.000    0.000    0.000    0.000 :0(replace)
        1    0.000    0.000    0.000    0.000 :0(repr)
        1    0.000    0.000    0.000    0.000 :0(rfind)
      354    0.002    0.000    0.002    0.000 :0(rpartition)
      977    0.004    0.000    0.004    0.000 :0(rstrip)
        1    0.000    0.000    0.000    0.000 :0(seed)
       25    0.000    0.000    0.000    0.000 :0(setattr)
        2    0.000    0.000    0.000    0.000 :0(setdefault)
        1    0.003    0.003    0.003    0.003 :0(setprofile)
        2    0.000    0.000    0.000    0.000 :0(sort)
   172718    1.104    0.000    1.104    0.000 :0(sorted)
        9    0.000    0.000    0.000    0.000 :0(split)
        1    0.013    0.013    0.013    0.013 :0(splitlines)
        1    0.000    0.000    0.000    0.000 :0(sqrt)
       14    0.000    0.000    0.000    0.000 :0(startswith)
      187    0.004    0.000    0.004    0.000 :0(stat)
    63896    0.314    0.000    0.314    0.000 :0(strip)
        4    0.000    0.000    0.000    0.000 :0(tolist)
        5    0.000    0.000    0.000    0.000 :0(translate)
        1    0.000    0.000    0.000    0.000 :0(union)
        4    0.000    0.000    0.000    0.000 :0(update)
        1    0.006    0.006    0.006    0.006 :0(utf_8_decode)
       73    0.001    0.000    0.001    0.000 <frozen importlib._bootstrap>:103(release)
       48    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:143(__init__)
       48    0.001    0.000    0.004    0.000 <frozen importlib._bootstrap>:147(__enter__)
       48    0.000    0.000    0.001    0.000 <frozen importlib._bootstrap>:151(__exit__)
       73    0.001    0.000    0.003    0.000 <frozen importlib._bootstrap>:157(_get_module_lock)
       47    0.001    0.000    0.001    0.000 <frozen importlib._bootstrap>:176(cb)
       25    0.000    0.000    0.002    0.000 <frozen importlib._bootstrap>:194(_lock_unlock_module)
     70/4    0.001    0.000    0.149    0.037 <frozen importlib._bootstrap>:211(_call_with_frames_removed)
      488    0.002    0.000    0.002    0.000 <frozen importlib._bootstrap>:222(_verbose_message)
        1    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:232(_requires_builtin_wrapper)
       44    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:307(__init__)
       44    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:311(__enter__)
       44    0.001    0.000    0.002    0.000 <frozen importlib._bootstrap>:318(__exit__)
      176    0.001    0.000    0.001    0.000 <frozen importlib._bootstrap>:321(<genexpr>)
       35    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:35(_new_module)
       45    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:369(__init__)
       78    0.001    0.000    0.006    0.000 <frozen importlib._bootstrap>:403(cached)
       72    0.000    0.000    0.001    0.000 <frozen importlib._bootstrap>:416(parent)
       44    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:424(has_location)
        1    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:433(spec_from_loader)
       44    0.002    0.000    0.010    0.000 <frozen importlib._bootstrap>:504(_init_module_attrs)
       44    0.001    0.000    0.018    0.000 <frozen importlib._bootstrap>:564(module_from_spec)
       47    0.001    0.000    0.001    0.000 <frozen importlib._bootstrap>:58(__init__)
     44/4    0.002    0.000    0.151    0.038 <frozen importlib._bootstrap>:651(_load_unlocked)
       45    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:707(find_spec)
        1    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:728(create_module)
        1    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:736(exec_module)
        1    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:753(is_package)
       73    0.001    0.000    0.001    0.000 <frozen importlib._bootstrap>:78(acquire)
       44    0.000    0.000    0.001    0.000 <frozen importlib._bootstrap>:780(find_spec)
      133    0.001    0.000    0.001    0.000 <frozen importlib._bootstrap>:843(__enter__)
      133    0.001    0.000    0.001    0.000 <frozen importlib._bootstrap>:847(__exit__)
       45    0.002    0.000    0.044    0.001 <frozen importlib._bootstrap>:870(_find_spec)
     48/3    0.001    0.000    0.156    0.052 <frozen importlib._bootstrap>:936(_find_and_load_unlocked)
     48/3    0.002    0.000    0.156    0.052 <frozen importlib._bootstrap>:966(_find_and_load)
    72/24    0.001    0.000    0.139    0.006 <frozen importlib._bootstrap>:997(_handle_fromlist)
        5    0.000    0.000    0.001    0.000 <frozen importlib._bootstrap_external>:1067(_path_hooks)
      106    0.001    0.000    0.003    0.000 <frozen importlib._bootstrap_external>:1080(_path_importer_cache)
       44    0.002    0.000    0.037    0.001 <frozen importlib._bootstrap_external>:1117(_get_spec)
       44    0.000    0.000    0.038    0.001 <frozen importlib._bootstrap_external>:1149(find_spec)
        5    0.000    0.000    0.001    0.000 <frozen importlib._bootstrap_external>:1196(__init__)
       40    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap_external>:1202(<genexpr>)
       43    0.001    0.000    0.002    0.000 <frozen importlib._bootstrap_external>:1228(_get_spec)
       89    0.007    0.000    0.031    0.000 <frozen importlib._bootstrap_external>:1233(find_spec)
        5    0.000    0.000    0.002    0.000 <frozen importlib._bootstrap_external>:1281(_fill_cache)
        5    0.000    0.000    0.001    0.000 <frozen importlib._bootstrap_external>:1310(<setcomp>)
        5    0.000    0.000    0.001    0.000 <frozen importlib._bootstrap_external>:1322(path_hook_for_FileFinder)
       70    0.003    0.000    0.009    0.000 <frozen importlib._bootstrap_external>:263(cache_from_source)
       43    0.001    0.000    0.006    0.000 <frozen importlib._bootstrap_external>:361(_get_cached)
       89    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap_external>:37(_relax_case)
       35    0.000    0.000    0.001    0.000 <frozen importlib._bootstrap_external>:393(_check_name_wrapper)
       35    0.001    0.000    0.003    0.000 <frozen importlib._bootstrap_external>:430(_validate_bytecode_header)
       35    0.001    0.000    0.011    0.000 <frozen importlib._bootstrap_external>:485(_compile_bytecode)
       70    0.000    0.000    0.001    0.000 <frozen importlib._bootstrap_external>:52(_r_long)
       43    0.001    0.000    0.001    0.000 <frozen importlib._bootstrap_external>:524(spec_from_file_location)
      453    0.005    0.000    0.016    0.000 <frozen importlib._bootstrap_external>:57(_path_join)
      453    0.006    0.000    0.009    0.000 <frozen importlib._bootstrap_external>:59(<listcomp>)
       70    0.001    0.000    0.002    0.000 <frozen importlib._bootstrap_external>:63(_path_split)
       35    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap_external>:669(create_module)
     35/4    0.001    0.000    0.149    0.037 <frozen importlib._bootstrap_external>:672(exec_module)
       35    0.002    0.000    0.024    0.001 <frozen importlib._bootstrap_external>:743(get_code)
      187    0.001    0.000    0.005    0.000 <frozen importlib._bootstrap_external>:75(_path_stat)
       35    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap_external>:800(__init__)
       35    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap_external>:825(get_filename)
       35    0.002    0.000    0.003    0.000 <frozen importlib._bootstrap_external>:830(get_data)
       35    0.000    0.000    0.001    0.000 <frozen importlib._bootstrap_external>:840(path_stats)
       63    0.001    0.000    0.002    0.000 <frozen importlib._bootstrap_external>:85(_path_is_mode_type)
        8    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap_external>:908(__init__)
        8    0.000    0.000    0.006    0.001 <frozen importlib._bootstrap_external>:919(create_module)
        8    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap_external>:927(exec_module)
       58    0.000    0.000    0.002    0.000 <frozen importlib._bootstrap_external>:94(_path_isfile)
        5    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap_external>:99(_path_isdir)
        1    0.000    0.000    0.000    0.000 <string>:1(<module>)
        1    0.000    0.000    0.000    0.000 <string>:5(DictionaryWithPredicate)
        1    0.000    0.000    0.000    0.000 TextSummaryExtractor.py:19(SummaryTool)
        1    0.000    0.000    0.000    0.000 TextSummaryExtractor.py:3(<module>)
        1    0.000    0.000    0.000    0.000 __future__.py:48(<module>)
        1    0.000    0.000    0.000    0.000 __future__.py:78(_Feature)
        9    0.000    0.000    0.000    0.000 __future__.py:79(__init__)
        1    0.000    0.000    0.000    0.000 __init__.py:1(<module>)
        1    0.000    0.000    0.004    0.004 __init__.py:3(<module>)
        1    0.000    0.000    0.002    0.002 __init__.py:357(namedtuple)
        2    0.000    0.000    0.023    0.012 __init__.py:4(<module>)
        2    0.000    0.000    0.000    0.000 __init__.py:420(<genexpr>)
        2    0.000    0.000    0.000    0.000 __init__.py:422(<genexpr>)
        1    0.000    0.000    0.120    0.120 __init__.py:6(<module>)
       43    0.000    0.000    0.000    0.000 _compat_pickle.py:165(<genexpr>)
       85    0.000    0.000    0.000    0.000 _compat_pickle.py:167(<genexpr>)
        1    0.000    0.000    0.001    0.001 _compat_pickle.py:9(<module>)
       14    0.000    0.000    0.000    0.000 abc.py:9(abstractmethod)
        1    0.000    0.000    0.003    0.003 bisect.py:1(<module>)
        1    0.000    0.000    0.000    0.000 codecs.py:347(__init__)
        1    0.000    0.000    0.000    0.000 codecs.py:422(__init__)
        1    0.000    0.000    0.007    0.007 codecs.py:450(read)
        1    0.000    0.000    0.020    0.020 codecs.py:603(readlines)
        1    0.000    0.000    0.000    0.000 codecs.py:678(__init__)
        1    0.000    0.000    0.020    0.020 codecs.py:704(readlines)
        1    0.000    0.000    0.000    0.000 codecs.py:744(__enter__)
        1    0.000    0.000    0.000    0.000 codecs.py:747(__exit__)
        1    0.000    0.000    0.000    0.000 codecs.py:862(open)
        5    0.000    0.000    0.000    0.000 copy.py:66(copy)
        1    0.000    0.000    0.000    0.000 datastore.py:115(Node)
   172718    1.404    0.000    1.404    0.000 datastore.py:116(__init__)
        1    0.000    0.000    0.000    0.000 datastore.py:122(DTrie)
        1    0.000    0.000    0.000    0.000 datastore.py:126(__init__)
        1    0.000    0.000    0.000    0.000 datastore.py:14(Queue)
      222    0.003    0.000    0.058    0.000 datastore.py:140(isWord)
      222    0.012    0.000    0.055    0.000 datastore.py:146(isWordAndTrie)
    63896    4.643    0.000   18.098    0.000 datastore.py:178(add)
        1    0.000    0.000    0.000    0.000 datastore.py:236(getAllWordsIterable)
518546/63897    8.297    0.000   11.944    0.000 datastore.py:239(getAllWordsIterableHelper)
        1    0.000    0.000    0.000    0.000 datastore.py:252(RTrie)
        1    0.000    0.000    0.000    0.000 datastore.py:285(TamilTrie)
        1    0.000    0.000    0.016    0.016 datastore.py:4(<module>)
        1    0.000    0.000    0.000    0.000 datastore.py:53(Trie)
        1    0.000    0.000    0.000    0.000 datastore.py:56(__init__)
    64097    0.641    0.000    8.865    0.000 datastore.py:60(get_letters_impl)
        1    0.000    0.000   32.675   32.675 demo.py:5(<module>)
        1    0.000    0.000    0.000    0.000 dictionary.py:111(Agarathi)
        1    0.000    0.000    0.000    0.000 dictionary.py:112(__init__)
    63896    0.657    0.000   18.755    0.000 dictionary.py:139(add)
      222    0.002    0.000    0.060    0.000 dictionary.py:145(isWord)
        1    0.000    0.000    0.000    0.000 dictionary.py:151(getDictionaryPath)
    63897    0.496    0.000   12.440    0.000 dictionary.py:157(getAllWordsIterable)
        1    0.000    0.000    0.000    0.000 dictionary.py:16(Dictionary)
        1    0.000    0.000    0.000    0.000 dictionary.py:170(EmptyAgarathi)
        1    0.000    0.000    0.000    0.000 dictionary.py:174(TamilVU)
        1    0.000    0.000    0.000    0.000 dictionary.py:175(__init__)
        1    0.000    0.000    0.000    0.000 dictionary.py:178(EnglishLinux)
        1    0.000    0.000    0.000    0.000 dictionary.py:189(VatamozhiMonierWilliams)
        1    0.000    0.000    0.000    0.000 dictionary.py:193(ParallelDictionary)
        1    0.000    0.000    0.000    0.000 dictionary.py:210(Madurai)
        1    0.000    0.000    0.000    0.000 dictionary.py:217(Wikipedia)
        1    0.000    0.000    0.000    0.000 dictionary.py:225(DictionaryBuilder)
        1    0.000    0.000   32.416   32.416 dictionary.py:226(create)
        1    0.000    0.000    0.023    0.023 dictionary.py:4(<module>)
        1    0.279    0.279   12.719   12.719 dictionary.py:47(getSize)
        1    0.608    0.608   19.697   19.697 dictionary.py:58(loadWordFile)
        1    0.000    0.000    0.000    0.000 dictionary.py:71(SimpleDictionary)
        1    0.000    0.000    0.014    0.014 encode2unicode.py:23(<module>)
        1    0.005    0.005    0.005    0.005 encode2utf8.py:24(<module>)
      166    0.001    0.000    0.003    0.000 enum.py:265(__call__)
      166    0.001    0.000    0.002    0.000 enum.py:515(__new__)
       33    0.000    0.000    0.000    0.000 enum.py:592(name)
        2    0.000    0.000    0.000    0.000 enum.py:597(value)
        2    0.000    0.000    0.001    0.001 enum.py:758(_missing_)
        2    0.000    0.000    0.001    0.001 enum.py:765(_create_pseudo_member_)
        9    0.000    0.000    0.002    0.000 enum.py:795(__or__)
       74    0.001    0.000    0.003    0.000 enum.py:801(__and__)
       11    0.000    0.000    0.000    0.000 enum.py:820(_high_bit)
        2    0.000    0.000    0.001    0.001 enum.py:837(_decompose)
        2    0.000    0.000    0.001    0.000 enum.py:855(<listcomp>)
        5    0.000    0.000    0.000    0.000 enum.py:866(<lambda>)
       15    0.000    0.000    0.000    0.000 enum.py:872(_power_of_two)
       14    0.000    0.000    0.005    0.000 hashlib.py:116(__get_openssl_constructor)
        1    0.000    0.000    0.010    0.010 hashlib.py:54(<module>)
        8    0.000    0.000    0.004    0.001 hashlib.py:73(__get_builtin_constructor)
        1    0.000    0.000    0.000    0.000 ipaconvert.py:24(<module>)
        1    0.000    0.000    0.003    0.003 numeral.py:5(<module>)
        1    0.000    0.000    0.000    0.000 orddic.py:5(<module>)
        1    0.000    0.000    0.005    0.005 pickle.py:181(<listcomp>)
        1    0.000    0.000    0.000    0.000 pickle.py:184(_Framer)
        1    0.000    0.000    0.000    0.000 pickle.py:220(_Unframer)
        1    0.000    0.000    0.013    0.013 pickle.py:24(<module>)
        1    0.000    0.000    0.000    0.000 pickle.py:345(_Pickler)
        1    0.000    0.000    0.000    0.000 pickle.py:64(PickleError)
        1    0.000    0.000    0.000    0.000 pickle.py:68(PicklingError)
        1    0.000    0.000    0.000    0.000 pickle.py:75(UnpicklingError)
        1    0.000    0.000    0.000    0.000 pickle.py:88(_Stop)
        1    0.000    0.000    0.000    0.000 pickle.py:986(_Unpickler)
        1    0.000    0.000    0.000    0.000 posixpath.py:102(split)
        1    0.000    0.000    0.000    0.000 posixpath.py:329(normpath)
        1    0.000    0.000    0.000    0.000 posixpath.py:367(abspath)
        2    0.000    0.000    0.000    0.000 posixpath.py:39(_get_sep)
        1    0.000    0.000    0.000    0.000 posixpath.py:62(isabs)
        1    0.000    0.000    0.000    0.000 pprint.py:35(<module>)
        1    0.000    0.000    0.000    0.000 pprint.py:72(_safe_key)
        1    0.000    0.000    0.000    0.000 pprint.py:98(PrettyPrinter)
        1    0.000    0.000   32.678   32.678 profile:0(<code object <module> at 0x102c77810, file "demo.py", line 5>)
        0    0.000             0.000          profile:0(profiler)
        1    0.000    0.000    0.000    0.000 qwertykbd.py:9(<module>)
        1    0.000    0.000    0.021    0.021 random.py:38(<module>)
        1    0.000    0.000    0.000    0.000 random.py:663(SystemRandom)
        1    0.000    0.000    0.000    0.000 random.py:71(Random)
        1    0.000    0.000    0.000    0.000 random.py:87(__init__)
        1    0.000    0.000    0.000    0.000 random.py:96(seed)
      102    0.001    0.000    0.004    0.000 re.py:169(match)
        2    0.000    0.000    0.020    0.010 re.py:231(compile)
        1    0.000    0.000    0.000    0.000 re.py:249(escape)
      104    0.001    0.000    0.022    0.000 re.py:286(_compile)
        1    0.000    0.000    0.000    0.000 regexp.py:5(<module>)
        1    0.000    0.000    0.000    0.000 resources.py:10(<listcomp>)
        1    0.000    0.000    0.000    0.000 resources.py:13(get_data_dir)
        1    0.000    0.000    0.000    0.000 resources.py:17(get_data_dictionaries)
        1    0.000    0.000    0.000    0.000 resources.py:28(get_data_categories)
       14    0.000    0.000    0.000    0.000 resources.py:42(mk_path)
        1    0.000    0.000    0.001    0.001 resources.py:5(<module>)
        1    0.000    0.000    0.000    0.000 resources.py:9(_make_dict_with_path)
        1    0.000    0.000    0.000    0.000 santhirules.py:4(<module>)
      164    0.001    0.000    0.002    0.000 sre_compile.py:102(fixup)
        8    0.000    0.000    0.005    0.001 sre_compile.py:223(_compile_charset)
        8    0.002    0.000    0.005    0.001 sre_compile.py:250(_optimize_charset)
        5    0.000    0.000    0.000    0.000 sre_compile.py:376(_mk_bitmap)
        5    0.000    0.000    0.000    0.000 sre_compile.py:378(<listcomp>)
        4    0.000    0.000    0.000    0.000 sre_compile.py:381(_bytes_to_codes)
        4    0.000    0.000    0.000    0.000 sre_compile.py:388(_simple)
        2    0.000    0.000    0.000    0.000 sre_compile.py:414(_get_literal_prefix)
        2    0.000    0.000    0.000    0.000 sre_compile.py:441(_get_charset_prefix)
        3    0.000    0.000    0.001    0.000 sre_compile.py:482(_compile_info)
        6    0.000    0.000    0.000    0.000 sre_compile.py:539(isstring)
        3    0.000    0.000    0.012    0.004 sre_compile.py:542(_code)
        3    0.000    0.000    0.022    0.007 sre_compile.py:557(compile)
     16/3    0.001    0.000    0.011    0.004 sre_compile.py:64(_compile)
       16    0.000    0.000    0.000    0.000 sre_parse.py:111(__init__)
       15    0.000    0.000    0.000    0.000 sre_parse.py:159(__len__)
       48    0.000    0.000    0.001    0.000 sre_parse.py:163(__getitem__)
        4    0.000    0.000    0.000    0.000 sre_parse.py:167(__setitem__)
       18    0.000    0.000    0.000    0.000 sre_parse.py:171(append)
    24/11    0.000    0.000    0.001    0.000 sre_parse.py:173(getwidth)
        3    0.000    0.000    0.000    0.000 sre_parse.py:223(__init__)
      329    0.001    0.000    0.001    0.000 sre_parse.py:232(__next)
       51    0.000    0.000    0.000    0.000 sre_parse.py:248(match)
      270    0.002    0.000    0.003    0.000 sre_parse.py:253(get)
        4    0.000    0.000    0.000    0.000 sre_parse.py:266(getuntil)
       24    0.000    0.000    0.000    0.000 sre_parse.py:285(tell)
        1    0.000    0.000    0.000    0.000 sre_parse.py:287(seek)
        3    0.000    0.000    0.000    0.000 sre_parse.py:342(_escape)
      8/3    0.000    0.000    0.009    0.003 sre_parse.py:407(_parse_sub)
     11/3    0.002    0.000    0.009    0.003 sre_parse.py:470(_parse)
        3    0.000    0.000    0.000    0.000 sre_parse.py:76(__init__)
       14    0.000    0.000    0.000    0.000 sre_parse.py:81(groups)
        3    0.000    0.000    0.001    0.000 sre_parse.py:828(fix_flags)
        4    0.000    0.000    0.000    0.000 sre_parse.py:84(opengroup)
        3    0.000    0.000    0.010    0.003 sre_parse.py:844(parse)
        4    0.000    0.000    0.000    0.000 sre_parse.py:96(closegroup)
        1    0.000    0.000    0.021    0.021 string.py:15(<module>)
        1    0.000    0.000    0.000    0.000 string.py:169(Formatter)
        1    0.000    0.000    0.000    0.000 string.py:55(_TemplateMetaclass)
        1    0.000    0.000    0.020    0.020 string.py:65(__init__)
        1    0.000    0.000    0.000    0.000 string.py:77(Template)
        1    0.001    0.001    0.002    0.002 tace16.py:358(<listcomp>)
        1    0.000    0.000    0.002    0.002 tace16.py:4(<module>)
        1    0.000    0.000    0.000    0.000 tamil99kbd.py:11(<module>)
        1    0.000    0.000    0.000    0.000 transliteration.py:23(<module>)
        1    0.001    0.001    0.002    0.002 tscii.py:13(<module>)
      256    0.001    0.000    0.001    0.000 tscii.py:16(<lambda>)
        1    0.000    0.000    0.000    0.000 tweetparser.py:12(TweetParser)
        1    0.000    0.000    0.000    0.000 tweetparser.py:60(TamilTweetParser)
        1    0.000    0.000    0.004    0.004 tweetparser.py:9(<module>)
       35    0.000    0.000    0.000    0.000 types.py:135(__get__)
        1    0.000    0.000    0.147    0.147 typographical.py:14(<module>)
    632/1    0.026    0.000    0.041    0.041 typographical.py:20(oridam_generate_patterns)
        1    0.001    0.001    0.102    0.102 typographical.py:50(corrections)
        1    0.000    0.000    0.000    0.000 unicode2encode.py:25(<module>)
        1    0.000    0.000    0.003    0.003 unicode2ipa.py:23(<module>)
        1    0.003    0.003    0.031    0.031 utf8.py:11(<module>)
        1    0.000    0.000    0.000    0.000 utf8.py:159(<listcomp>)
      288    0.001    0.000    0.001    0.000 utf8.py:234(uyir_len)
      288    0.001    0.000    0.001    0.000 utf8.py:237(mei_len)
      288    0.003    0.000    0.005    0.000 utf8.py:274(uyirmei_constructed)
    98518    1.125    0.000    1.940    0.000 utf8.py:303(<lambda>)
        4    0.000    0.000    0.000    0.000 utf8.py:384(_make_set)
    64097    4.222    0.000    8.224    0.000 utf8.py:393(get_letters)
        1    0.000    0.000    0.000    0.000 utf8.py:758(CacheGetLettersMixin)
        1    0.000    0.000    0.000    0.000 utf8.py:760(__init__)
    64118    0.895    0.000   10.059    0.000 utf8.py:767(get_letters)
        1    0.000    0.000    0.000    0.000 wordutils.py:310(DictionaryFixedWordList)
        1    0.000    0.000    0.029    0.029 wordutils.py:4(<module>)

Basically, this confirms solthiruthi, and similar search based spellers, as a computational problem for Tamil spell checkers claimed in our paper. Performance is all it takes to make the results better, more accurate and faster.

2021

இணைமதி எழுத்துரு கொண்டு செய்யப்பட்ட தமிழ் அரிச்சுவடி

புத்தாண்டில் பல புதிய வாய்புகள், சந்தர்ப்பங்கள் காத்திருக்கின்றன; நமது திறன்களை வளர்த்துக்கொள்ளவும் வாய்ப்பு உண்டு; சென்ற ஆண்டில் நடப்பில் குறைபாடுகளையும் சீர்மைசெய்ய வாய்ப்பு உண்டு. இன்று எனது பார்வையில், எழில் மொழி அறக்கட்டளையின் பணிகளானது தொடர்ந்து இந்த ஆண்டில் நடைபெரும்:

  1.  சில சிக்கலான தமிழ் மொழிபெயர்ப்புகளை முடிப்பது (compiler பற்றிய கட்டுரை, தமிழில் அல்கொரிதம் பற்றியும் தகவல் தரவமைப்புகள் பற்றியும் புத்தகங்கள்).
  2. நிரல் அளவில் இரண்டு அல்லது மூன்று ஓப்பன் தமிழ் வெளியீடுகளை ஏற்பாடு செய்வது
  3. புதிய திட்டங்கள் அளவில் விட்டர்பீ அல்கொரிதத்தின் வாயிலான தமிழ் சொல்திருத்தி செயல்பாட்டிற்கு தீர்வு காணுதல்.

புடிச்சா புளியங்கொம்பு; முயற்சிகள் வீண்போவதில்லை. சவால்களை சந்திப்போம்.

அன்புடன்

-முத்து

சில பைத்தான் தொகுப்புகளின் வெளியீடு

இரண்டு பைத்தான் சொற்பிழை திருத்திகளை சமிபத்தில் எளிதாக பயன்படுத்தும் வண்ணம் “பொட்டலம்” போட்டேன். அதாவது மளிகைக்கடைகளில் அரிசி பருப்பு வகைகள் சாக்குகளில் இருந்தாலும் மொத்தவிலை கடைகளில்லாமல் தனியார் செல்லும் நகர கடைகளில் இவை பொட்டலங்களாக “பாக்கேட்” செய்து, நமது நேர நெருக்கடிக்காக, விற்கப்படும். அதே போல பல நல்ல நிரல்கள் பொதுவிலும், கிட் ஹபிலும் இருந்தாலும், இவற்றை பொதுவில் நிரலர்கள் பயன்படுத்த நாம் இதனை பொட்டலம் செய்தும், அரிசியில் கற்களை பொறக்கியெடுத்தும் சீர்செய்து மளிகைக்கடைக்காரர் செய்வார் இல்லையா, பரிசோதித்தும் வெளியிட்டுள்ளேன்.

1. தமிழிணையவாணி

Python package released for Tamilinaya-Spellchecker by @tshrinivasan and team’s work (based on @Neechalkaran creation) http://pypi.org/project/tamilinayavaani/0.13/ Windows, Mac and Linux users can get the package by command:

$ pip install tamilinayavaani==0.13

Demo co-lab: here

2. தமிழ்சொற்பிழைதிருத்தி

Packaged tamilspellchecker https://github.com/malaikannan/TamilSpellChecker from @malai_san +team for Python https://pypi.org/project/tamilspellchecker/0.10/ – APACHE 2.0. Get your copy:

$ pip install tamilspellchecker>=0.10

Demo co-lab: here

ஓப்பன் தமிழ் வரிசைஎண்0.98 வெளியீடு

open-tamil v0.9 release.
ஓப்பன் தமிழ் வரிசை எண்: 0.98

வணக்கம் நண்பர்களே!

சென்ற வாரம் நவம்பர் மாதம் 13ஆம் நாள் அன்று open-tamil வரிசை எண் 0.98 வெளியீடு ஆனது; இந்த நிரல் தொகுப்பை பைத்தான் மொழியில் பெற,

$ pip install –upgrade open-tamil >=0.98

என்ற கட்டளைகள கொடுக்கலாம்.

இதில் புதிதாக சிறு வழு நீக்கங்கள் உள்ளன,

  1. தமிழ் மாத்திரை கணக்கிடும் சேவை திருத்தம் செய்யப்பட்டது; (tamil.utf8.total_maaththirai)
  2. tamil.regexp மோட்யூல் சீர்செய்து வழு நீக்கம் செய்யப்பட்டது; (வழு 228)

அன்புடன்,

(ஓப்பன் தமிழ் குழுவிற்காக) முத்து

கலிபோர்னியா

உயிர் எழுத்துக்கள்

இணைமதி எழுத்துருவில்; அச்சிட்டு விளையாடலாம். மனைவி, சாலா, கோரிக்கைக்கு ஒரு கலை திட்டம்/விளையாட்டு உருவாக்குவதற்கு இதனை செய்தோம்; வானவில் போன்ற நிரங்களில் (ROYGBIV) என்ற வரிசையில் நிரங்கள் உள்ளன.

வண்ணங்களும் எழுத்துக்களும் கண்டால் இதைப்போன்ற திட்டங்களிலும் செயலிகளையும் உருவாக்கவேண்டும் என்றும் ஒருவித ஏக்கம் தோன்றுகிறது. காண்பதெல்லாம் கண்களை குளிரவைக்கும் வட்டெழுத்துக்கள்.

மாத்திரை பார்வையில் குறள்

                    ஆசிரியர்: பரதன் தியாகலிங்கம், முத்து அண்ணாமலை

திருக்குறள் 1330 குறட்பாக்களை மாத்திரை பார்வையில் கணினிவழியாக இயல்மொழி ஆய்வு செய்தால் என்ன கிடைக்கும்? திருக்குறளை மாத்திரை மதிப்பின் வாயிலாக வரிசைப்படுத்திப் பார்த்தால் என்ன கிடைக்கும் ? ஏதேனும் புதிய புரிதல் உண்டாகிறதா? பார்க்கலாம் வாருங்கள்.

செய்முறை – அல்கோரிதம்

குறளின் மாத்திரை அளவு என்பது குறளின் உள்ள அனைத்து சீர்பிரிக்காத சொற்களின் தனி மாத்திரை அளவுகளின் சமன்பாடு என்று கொள்ளலாம். இது நமது ஆய்வின் முன்கூட்டிய புரிதல்.

முதலில் இதற்கு ஒரு தமிழில் உள்ள மாத்திரை விதிகளை கணிக்கும் சார்பு தேவைப்படுகிறது. இதனை open-tamil 0.97 தொகுப்பில் ‘tamil.utf8.total_maththirai’ என்ற நிரல்துண்டு வழுங்குகிறது. மேலும் குறட்பக்களை ‘kural.Thirukkural().get_kural_no()’ என்பதிலிருந்து பெரலாம். இரண்டினையும் சேர்த்து ஒரு சிரிய கோவ்சியன் வளையம் பொருத்தலுடன் இணைத்துப்பார்த்தால் இப்படி தெரிகிறது; இதன் மூல நிரல் kural_mathirai.py என்பதில் காணலாம்.

#!/usr/bin/env python3
# This Python file uses the following encoding: utf-8
from kural import Thirukkural
from tamil.utf8 import get_letters, get_tamil_words, total_maaththirai
from collections import Counter, OrderedDict
from pprint import pprint
import matplotlib.pyplot as plt
import matplotlib
import numpy as np
from scipy.optimize import curve_fit

# Define model function to be used to fit to the data above:
def gauss(x, *p):
    A, mu, sigma = p
    return A*np.exp(-(x-mu)**2/(2.*sigma**2))

def main():
    eq = Counter()
    eqd = {}
    kural = Thirukkural()
    for kural_no in range(1330):
        kural_words = get_tamil_words(get_letters(kural.get_kural_no(kural_no+1).ta))
        mathirai = sum([total_maaththirai(word) for word in kural_words])
        if eq[mathirai] == 0:
                eqd[mathirai] = [kural_no+1]
        else:
            eqd[mathirai].append(kural_no+1)
        eq[mathirai] += 1
    eq_sorted=OrderedDict(sorted(eq.items(),key=lambda x: x))
    print("total = ",sum(eq.values()))
    plt.scatter(eq_sorted.keys(),eq_sorted.values())
    plt.ylabel(u'குறட்பாக்கள் எண்ணிக்கை',{'fontname':'Catamaran'})
    plt.xlabel(u'மாத்திரை அளவு',{'fontname':'Catamaran'}) #Arial Unicode MS'})

    # p0 is the initial guess for the fitting coefficients (A, mu and sigma above)
    p0 = [75., 20., 5.]
    coeff, var_matrix = curve_fit(gauss, list(eq_sorted.keys()), list(eq_sorted.values()), p0=p0)

    # Get the fitted curve
    hist_fit = gauss(list(eq_sorted.keys()), *coeff)
    plt.plot(eq_sorted.keys(), hist_fit, label='Gaussian Fitted data (mean=%g, std=%g)'%(coeff[1],coeff[2]))
    plt.title(r'குறள் மாத்திரை வரிசை (Gauss \mu=%g, \sigma=%g)'%(coeff[1],coeff[2]),{'fontname':'Catamaran'})

    # Finally, lets get the fitting parameters, i.e. the mean and standard deviation:
    print ('Fitted mean = ', coeff[1])
    print('Fitted standard deviation = ', coeff[2])

    plt.show()


if __name__ == "__main__":
    main()
திருக்குறள் மாத்திரை வரிசை ஒத்திய குறட்பா எண்ணிக்கை

விடைகள்

  1. திருக்குறளில் உள்ள சராசரி குறட்பாவின் மாத்திரை அளவு μ ~ 29.5. இதன் மாற்றமளவு σ ~ 2.5
  2. மாத்திரை பார்வையில் திருக்குறள் ஏரக்குறைய கௌசியன் பரப்பை போல் அமைந்துள்ளது
  3. திருக்குறள் மாத்திரை வடிவிலும் கூட அழகிய சீர்மை கொண்டதாக மிகவும் கோர்வையுடன் அமைந்தது.
  4. குறைந்த அளவு நமாத்திரை  நீளம் (23) கொண்ட குறளானவை குறள் எண்கள், 391, 426, 483, 786

“கற்க கசடறக் கற்பவை கற்றபின்
நிற்க அதற்குத் தக.” குறள் 391.

  1. அதிக அளவு நீளமான மாத்திரை (37.5) கொண்ட குறளானது குறள் வரிகள்,

”காணாதான் காட்டுவான் தான்காணான் காணாதான்
கண்டானாம் தான்கண்ட வாறு.” குறள் 849.

மத்திரை அளவுகுறள் எண்ணிக்கை                 குறள் எண்(கள்)
234391, 426, 483, 786
23.5567, 77, 366, 637, 979
248108, 485, 961, 965, 1042, 1048, 1277, 1304
24.57304, 467, 602, 652, 1118, 1322, 1324
2520133,
193,
331,
360,
412,
477,
546,
559,
576,
592,
616,
771,
796,
846,
947,
1052,
1116,
1239,
1240,
1289
25.52996,
339,
347,
350,
373,
400,
405,
439,
444,
569,
625,
669,
742,
764,
841,
937,
944,
978,
980,
1045,
1072,
1085,
1102,
1108,
1176,
1203,
1258,
1318,
1329
26371,
28,
40,
90,
152,
229,
308,
314,
340,
454,
466,
480,
488,
594,
622,
639,
666,
668,
687,
692,
715,
774,
824,
847,
856,
934,
964,
975,
988,
1008,
1028,
1168,
1238,
1242,
1256,
1279,
1309
26.54645,
54,
107,
168,
175,
196,
236,
296,
364,
451,
484,
516,
518,
531,
540,
571,
572,
598,
608,
611,
623,
628,
700,
706,
708,
738,
769,
838,
854,
877,
935,
954,
1010,
1066,
1071,
1131,
1132,
1134,
1222,
1224,
1227,
1229,
1232,
1233,
1296,
1302
277380,
105,
109,
119,
120,
121,
172,
173,
174,
202,
224,
231,
283,
284,
292,
321,
337,
341,
349,
374,
380,
399,
411,
428,
429,
438,
447,
489,
505,
508,
512,
520,
552,
562,
570,
578,
599,
604,
651,
654,
661,
693,
698,
729,
747,
770,
772,
778,
790,
803,
805,
807,
817,
818,
822,
832,
851,
863,
887,
889,
963,
994,
1019,
1041,
1069,
1107,
1120,
1122,
1159,
1173,
1300,
1321,
1326
27.58821,
34,
39,
64,
73,
87,
95,
98,
111,
115,
124,
131,
140,
157,
205,
207,
208,
210,
215,
239,
261,
270,
272,
280,
293,
309,
315,
336,
388,
394,
419,
431,
457,
465,
468,
469,
482,
491,
494,
495,
542,
543,
545,
554,
558,
574,
575,
581,
629,
653,
657,
679,
690,
705,
739,
759,
788,
811,
821,
823,
835,
876,
878,
882,
883,
904,
918,
949,
1004,
1023,
1039,
1063,
1091,
1105,
1109,
1117,
1138,
1144,
1156,
1165,
1166,
1226,
1257,
1266,
1273,
1281,
1283,
1301
2810413,
14,
60,
63,
75,
85,
89,
101,
103,
123,
145,
158,
167,
186,
191,
195,
213,
218,
230,
234,
302,
327,
369,
408,
410,
416,
425,
434,
463,
464,
472,
475,
478,
500,
504,
521,
522,
535,
549,
563,
580,
595,
596,
609,
618,
620,
621,
636,
664,
677,
703,
741,
748,
752,
767,
793,
797,
802,
816,
844,
873,
880,
884,
917,
925,
943,
984,
1003,
1011,
1013,
1031,
1040,
1043,
1051,
1080,
1086,
1088,
1092,
1096,
1099,
1100,
1114,
1135,
1137,
1141,
1146,
1153,
1157,
1177,
1178,
1184,
1199,
1201,
1208,
1210,
1216,
1221,
1259,
1264,
1295,
1306,
1307,
1327,
1330
28.59529,
68,
102,
104,
112,
114,
116,
132,
137,
153,
203,
223,
227,
238,
244,
255,
265,
267,
268,
274,
277,
295,
303,
316,
333,
342,
372,
381,
385,
392,
393,
398,
401,
403,
407,
437,
493,
506,
511,
517,
553,
577,
591,
601,
605,
631,
655,
671,
674,
696,
710,
723,
727,
740,
744,
749,
757,
763,
781,
809,
819,
829,
839,
852,
871,
941,
986,
996,
1025,
1050,
1061,
1062,
1073,
1093,
1098,
1119,
1142,
1152,
1164,
1170,
1196,
1209,
1213,
1223,
1249,
1250,
1268,
1280,
1287,
1290,
1298,
1308,
1310,
1315,
1328
299123,
26,
59,
76,
99,
113,
169,
181,
184,
197,
214,
233,
237,
254,
262,
264,
289,
313,
329,
334,
335,
338,
384,
427,
503,
539,
544,
547,
588,
590,
597,
607,
619,
630,
634,
638,
672,
707,
709,
712,
728,
754,
779,
785,
787,
791,
810,
812,
813,
826,
830,
837,
848,
853,
879,
888,
898,
905,
920,
942,
955,
971,
1014,
1021,
1034,
1068,
1084,
1089,
1110,
1121,
1126,
1139,
1143,
1147,
1149,
1151,
1172,
1193,
1200,
1211,
1231,
1237,
1245,
1247,
1251,
1253,
1271,
1276,
1292,
1299,
1305
29.51069,
33,
53,
55,
61,
66,
71,
79,
100,
136,
150,
154,
171,
177,
182,
192,
216,
226,
259,
279,
288,
290,
306,
310,
323,
344,
352,
363,
371,
375,
376,
377,
378,
404,
414,
418,
440,
448,
449,
455,
486,
497,
501,
527,
532,
585,
589,
593,
603,
641,
644,
650,
688,
697,
704,
726,
731,
734,
736,
743,
746,
751,
761,
765,
782,
801,
814,
815,
831,
836,
842,
850,
870,
872,
899,
922,
933,
945,
953,
958,
970,
974,
982,
997,
1000,
1038,
1053,
1065,
1067,
1095,
1111,
1113,
1128,
1161,
1171,
1219,
1228,
1234,
1235,
1236,
1244,
1252,
1254,
1261,
1284,
1297
3011619,
22,
48,
49,
57,
78,
97,
117,
122,
125,
129,
142,
151,
178,
180,
201,
217,
220,
241,
245,
250,
257,
260,
269,
273,
276,
286,
300,
332,
348,
353,
362,
365,
370,
420,
421,
432,
435,
436,
443,
470,
474,
479,
490,
498,
499,
507,
509,
524,
529,
534,
556,
565,
568,
610,
613,
626,
633,
640,
647,
659,
663,
676,
684,
714,
725,
750,
775,
776,
784,
798,
799,
800,
828,
864,
869,
885,
886,
890,
891,
892,
893,
902,
907,
916,
946,
948,
951,
962,
999,
1015,
1016,
1044,
1047,
1049,
1055,
1056,
1074,
1076,
1082,
1124,
1125,
1127,
1155,
1175,
1179,
1180,
1183,
1204,
1207,
1217,
1230,
1243,
1263,
1282,
1319
30.58510,
32,
58,
62,
83,
84,
88,
92,
139,
179,
200,
209,
235,
243,
251,
287,
291,
294,
297,
299,
320,
322,
346,
356,
367,
386,
396,
415,
430,
441,
442,
458,
459,
519,
525,
537,
557,
567,
624,
645,
656,
665,
678,
701,
717,
724,
773,
783,
789,
855,
859,
895,
906,
912,
915,
977,
992,
995,
1012,
1024,
1029,
1059,
1078,
1087,
1090,
1094,
1103,
1106,
1115,
1129,
1140,
1145,
1163,
1214,
1225,
1262,
1265,
1274,
1275,
1291,
1293,
1303,
1313,
1320,
1323
319216,
17,
18,
30,
37,
46,
50,
70,
72,
74,
93,
106,
135,
138,
144,
146,
160,
161,
190,
198,
204,
211,
222,
307,
319,
351,
358,
382,
383,
390,
406,
422,
460,
471,
473,
496,
523,
528,
538,
555,
561,
566,
587,
600,
612,
615,
648,
670,
702,
716,
721,
737,
753,
760,
768,
795,
820,
843,
857,
862,
866,
874,
903,
909,
985,
987,
989,
991,
1018,
1020,
1030,
1037,
1054,
1060,
1077,
1123,
1130,
1136,
1154,
1158,
1162,
1169,
1185,
1188,
1189,
1198,
1206,
1218,
1260,
1278,
1288,
1314
31.5703,
4,
11,
36,
41,
65,
69,
81,
110,
189,
242,
258,
263,
275,
278,
324,
354,
355,
359,
361,
379,
413,
417,
476,
481,
510,
536,
541,
573,
579,
586,
614,
617,
649,
658,
680,
694,
718,
722,
755,
766,
794,
804,
845,
858,
860,
867,
913,
914,
923,
926,
928,
936,
952,
956,
957,
976,
990,
998,
1022,
1026,
1027,
1033,
1035,
1075,
1104,
1167,
1182,
1248,
1255
325912,
44,
52,
128,
143,
156,
164,
165,
185,
188,
228,
253,
298,
311,
312,
345,
357,
389,
395,
433,
445,
450,
513,
530,
560,
564,
606,
642,
673,
686,
711,
730,
732,
735,
758,
762,
777,
792,
825,
833,
840,
881,
919,
968,
1036,
1057,
1058,
1081,
1112,
1160,
1174,
1197,
1212,
1215,
1272,
1294,
1311,
1316,
1325
32.5512,
20,
24,
31,
35,
47,
82,
86,
118,
147,
148,
159,
162,
176,
187,
271,
281,
282,
328,
446,
502,
514,
526,
533,
550,
582,
583,
662,
683,
699,
719,
720,
827,
861,
865,
908,
921,
927,
969,
981,
1097,
1150,
1181,
1186,
1187,
1191,
1194,
1195,
1241,
1286,
1312
33378,
155,
170,
183,
206,
212,
225,
248,
249,
318,
325,
368,
402,
462,
492,
548,
627,
646,
675,
685,
756,
780,
808,
834,
911,
939,
1046,
1070,
1083,
1101,
1148,
1190,
1192,
1269,
1270,
1285,
1317
33.53027,
194,
219,
221,
305,
317,
343,
456,
461,
632,
643,
667,
689,
806,
896,
900,
901,
930,
932,
959,
966,
972,
993,
1001,
1005,
1009,
1133,
1205,
1220,
1267
342338,
51,
56,
126,
134,
166,
252,
266,
330,
453,
487,
660,
681,
682,
695,
897,
910,
938,
950,
960,
967,
1007,
1032
34.5125, 42, 130, 149, 232, 387, 424, 733, 931, 983, 1006, 1079
351691,94,141,199,246,247,423,452,635,691,875,924,
973,1002,1017,1064
35.5925, 163, 285, 301, 515, 584, 868, 894, 929
3647, 409, 713, 745
36.56127, 240, 326, 551, 1202, 1246
37215, 940
37.5243, 397
3826, 256
39.51849

Python வழு நீக்கம் – PDB Debugging

ஆசிரியர்: லிசா டாக்லியபெரி,

தமிழாக்கம்: முத்து அண்ணாமலை.

This article is a translation of tutorial article on PDB from DigitalOcean; இந்த கட்டுரை ஏற்கனவே வெளியீடான பயிற்சி கட்டுரை தமிழாக்கம் ஆகும்.

சுருக்கம்: பல சமயங்களில் நாம் எழுதிய நிரல்கள் நமது எண்ணம் போல இயங்குவதில்லை; இதை சரிசெய்ய திக்குத்தெரியாத காட்டில் தேவை ஒரு வழு நீக்கி என்ற செயலி; பைத்தான் மொழியில் இது pdb – இதன் செயல்பாடு சில சிறப்பம்சங்கள் பற்றி இங்கு பார்க்கலாம்.

கணினி துறையில் நிரலராக (programmer) செயல்படுவதில் ஒருவரி முக்கியாமாக பெற்றுக்கொள்ளும் திறமை வழுநீக்கம் – அதாவது debugging. விளையாட்டாக பேசுகையில் வழுநீக்கம் என்பதன் ஆங்கில சொல்லின் பகுதி-விகுதிகளை பிரித்துப்பார்த்தால், அது புழு/பூச்சி நீக்கம் என்றும் அசட்டுத்தனமாக இருக்கும். இதனை வேடிக்கையாக இப்படி ஒரு படத்தில் அந்தகாலத்து கணினியில் காட்டினார்கள்!

Computer Bug

தொடர்வது லிசா எழுதிய https://www.digitalocean.com/community/tutorials/how-to-use-the-python-debugger இந்த 2017-ஆம் ஆண்டு கட்டுரையின் தமிழாக்கம்.

அறிமுகம்

கணினி உருவாக்கம் மற்றும் கட்டமைப்பில் வழுநீக்கம் என்பது கணினி செயலியின் தவறான/பிழையாக இயங்கும் இடங்களை மூல நிரலில் தேடிக் கண்டறிந்தும் பின் அவ்வகையான பிழைகளை நீக்கம் செய்யும் படிநிலை செயல்பாட்டிற்கு அளிக்கப்படும் பெயராகும்.

பைத்தான் மொழியில் pdb என்ற ஒரு வழு நீக்கி செயலி உள்ளது; இது python மொழியில் எழுதிய நிரல்களுக்கு ஒரு வழுநீக்கம் செய்யும் சூழலை அளிக்கிறது. pdb மூலம் நிபந்தனை நிறுத்தங்கள் (conditional breakpoints), வரிவரியான கண்காணிப்பு இயக்கம் (stepping through the source code one line at a time), அடுக்கு கண்கானிப்பு (stack inspection), என பல வைகயான உத்திகளைக்கொண்டு நிரலின் இயக்க நிலைகளை காணமுடிகிறது.

pdbஐ படிப்படியாக பயன்படுத்துதல்

பைத்தான் மொழியில் தரப்படுத்தப்பட்ட ஒரு நிரல்தொகுப்பு (module) வழியாக இந்த pdb வழுநீக்கி நமக்கு கிடைக்கிறது. இந்த Pdb வழுநீக்கியையே நீட்சி செய்து நாம் ஒரு நிரல்கூட எழுதலாம்க். pdb பற்றிய மூல ஆவணத்தை இங்கு படிக்கலாம்.

pdb பற்றி கற்றுக்கொள்ள நாம் ஒரு சின்ன நிரலின் வழுநீக்கம் வழியாக கற்றுக்கொள்ளலாம்; இந்த நிரலில் இரு பொதுவெளி மாறிகள் (global variables), ஒரு நிரல்பாக சார்பும் (function) அதனுள் உள்ள அடுக்கு மடக்கு வாக்கியமும் (loop), இவை அனைத்தையும் தொடங்கிவைக்கும் if __name__ == '__main__': என்ற நிரல்தொடக்க நிபந்தனையும் (அதாவது சார்பு nested_loop() என்பதை தொடக்கிவிடும்) வகையில் அமைந்தது இந்த நிரல் looping.py

num_list = [500, 600, 700]
alpha_list = ['x', 'y', 'z']

def nested_loop():
    for number in num_list:
        print(number)
        for letter in alpha_list:
            print(letter)

if __name__ == '__main__':
    nested_loop()

பைத்தான் வழுநீக்கம் என்பதை நமது நிரலில் தொடங்க இவ்வாறு கட்டளை அளிக்க வேண்டும்:

python -m pdb looping.py

இந்த -m என்ற flag பைத்தான் moduleஐ ஒரு நிரலாக இயக்க வழிசெய்யும். மேல் கண்டபடி கட்டளையிட்டால் நமது நிரல் (looping.py) பைத்தான் வழு நீக்கியான pdb-யினைக்கொண்டு அதன் கண்காணிப்பில் இயங்கும்.

மேல்கண்ட கட்டளை இயங்கியதும் இவ்வறு வெளியீடை காணலாம்:

Output> /Users/sammy/looping.py(1)<module>()
-> num_list = [500, 600, 700]
(Pdb) 

இதில், முதல் வரியில் (அதாவது <module> என்ற வரி) நிரல் கோப்பின் இருப்பிடம், மற்றும் நிரலின் இயங்கும் வரி (இங்கு முதல் வரி இயங்குகிறது). ‘->’ என்ற குறியிடின் அடுத்து வரும் வரி நிரலின் தற்சமயம் உள்ள இயக்கப்புள்ளியைச் சேர்ந்த வரியாகும். வழு நீக்கியின் திறன்கள் மற்றும் கட்டளைகளை பற்றி கற்றுக்கொள்ள  help <கட்டளை>  என்று கட்டளையின் பெயரை pdb shell-இல் இட்டு அந்த கட்டளையினைப்பற்றி குறிப்பாக கற்றுக்கொள்ளலாம். pdb கட்டளை திறை என்பதும் பைத்தான் console என்பதும் வெவ்வேரான விஷயங்கள் என்பதை கருத்தில் கொள்ள வேண்டும்.

pdb வழு நீக்கி நிரலின் இருதியில் மீண்டும் தொடங்கும் வகை கட்டமைக்கப்பட்டது; இதில் இருந்து வெளியேர quit அல்லது exit என்று கட்டளையிடவேண்டும். மேலும் நிரலின் ஏதேனும் குறிப்பிட்ட வரியில் இருந்து இயக்கத்தை தொடர வேண்டும் என்றால் run என்ற கட்டளையை pdb வழுநீக்கியால் செலுத்தலாம்.

வழு நீக்கியில் நிரல் இயக்கத்தை கண்கானித்தல்

pdb கட்டளைகளான list, step, மற்றும் next உங்களது நிரல் இயக்கத்தை கண்கானிக்கலாம். இந்த கட்டளைகளைப்பற்றி விரிவாக இந்த பத்தியில் பார்க்கலாம்.

pdb shell அதனில் list என்ற கட்டளையை இட்டால் தற்சமயம் இயங்கும் புள்ளியின் வரியின் சுற்றத்தில் உள்ள வரிகளை பார்க்கலாம்.  உதாரணமாக looping.py நிரலின் முதல் வரியின் சுற்றத்தில் — num_list = [500, 600, 700] — இப்படி வெளியீடு அளிக்கும்:

(Pdb) list
  1  -> num_list = [500, 600, 700]
  2     alpha_list = ['x', 'y', 'z']
  3     
  4     
  5     def nested_loop():
  6         for number in num_list:
  7             print(number)
  8             for letter in alpha_list:
  9                 print(letter)
 10     
 11     if __name__ == '__main__':
(Pdb) 

‘->’ என்ற குறியிடின் அடுத்து வரும் வரி நிரலின் தற்சமயம் உள்ள இயக்கப்புள்ளியைச் சேர்ந்த வரியாகும்.

நமது இந்த நிரல் சற்று சிறிதாக உள்ளதால் முழு நிரலையும் list கட்டளை இங்கு அளித்துவிடுகிறது. சராசரியான பயன்பாட்டில் list கட்டளை 11 வரிகளையும் முழுதாக வெளியிடுகிரது; ஆனால் list 3, 7 வரிகள் 3-இல் இருந்து 7-வரை மட்டும் வெளியிட வேண்டுமெனில் கீழ்கண்டபடி கட்டளையிடவும்: list 3, 7

(Pdb) list 3, 7
  3     
  4     
  5     def nested_loop():
  6         for number in num_list:
  7             print(number)
(Pdb) 

செயலியின் இயக்கத்தை நிரல் வரிகளில் ஒவ்வொரு வரியாக அலசுவதற்கு step அல்லது next கட்டளைகளை பயன்படுத்தலாம்; உதாரணம்:

(Pdb) step
> /Users/sammy/looping.py(2)<module>()
-> alpha_list = ['x', 'y', 'z']
(Pdb) 

(Pdb) next
> /Users/sammy/looping.py(2)<module>()
-> alpha_list = ['x', 'y', 'z']
(Pdb) 

step என்ற கட்டளைக்கும் next என்ற கட்டளைக்கும்  வித்தியாசமானது step என்பது சார்புகள், நிரல்துண்டுகளை கடக்கும்பொழுது அது நிறுத்தம் அடையும், ஆனால் next கட்டளை சார்புகளை முழுதாக இயகிய பின்னரே அதனை அடுத்த வரியில் சென்று நிற்கும்.

step கட்டளை மடக்கு வாக்கியங்களில் படிபடியாக ஒவ்வொரு வரியிலும் நிறுத்தி இயக்கத்தைக் காட்டும்; இதனைக்கொண்டு மாறிகளின் மதிப்புகள், மாறிகளை அச்சிடுவது, print(number), என்றும் letter என்றதை அச்சிடுவதும் print(letter), return number என்ற வரியை செயல்படுத்துவதையும் பார்க்கலாம்.

(Pdb) step
> /Users/sammy/looping.py(5)<module>()
-> def nested_loop():
(Pdb) step
> /Users/sammy/looping.py(11)<module>()
-> if __name__ == '__main__':
(Pdb) step
> /Users/sammy/looping.py(12)<module>()
-> nested_loop()
(Pdb) step
--Call--
> /Users/sammy/looping.py(5)nested_loop()
-> def nested_loop():
(Pdb) step
> /Users/sammy/looping.py(6)nested_loop()
-> for number in num_list:
(Pdb) step
> /Users/sammy/looping.py(7)nested_loop()
-> print(number)
(Pdb) step
500
> /Users/sammy/looping.py(8)nested_loop()
-> for letter in alpha_list:
(Pdb) step
> /Users/sammy/looping.py(9)nested_loop()
-> print(letter)
(Pdb) step
x
> /Users/sammy/looping.py(8)nested_loop()
-> for letter in alpha_list:
(Pdb) step
> /Users/sammy/looping.py(9)nested_loop()
-> print(letter)
(Pdb) step
y
> /Users/sammy/looping.py(8)nested_loop()
-> for letter in alpha_list:
(Pdb)

ஒரு முழு சார்பு/நிரல்பாத்தினை next கட்டளை வழியாக செயல்படுத்தலாம் – இது படிநிலை இயக்கம் இல்லாமல் குறிப்பிட்ட சார்பினை முழுதாக கடந்து செல்லும். வழு நீக்கியை விட்டு வெளியேற exit கட்டளையிடவும். அதன்பின் மீண்டும் வழுநீக்கியை தொடங்கவும்:

python -m pdb looping.py

இப்பொழுது next கட்டளையின் செயல்பாடை காணலாம்:

(Pdb) next
> /Users/sammy/looping.py(5)<module>()
-> def nested_loop():
(Pdb) next
> /Users/sammy/looping.py(11)<module>()
-> if __name__ == '__main__':
(Pdb) next
> /Users/sammy/looping.py(12)<module>()
-> nested_loop()
(Pdb) next
500
x
y
z
600
x
y
z
700
x
y
z
--Return--
> /Users/sammy/looping.py(12)<module>()->None
-> nested_loop()
(Pdb)  

உங்கள் நிரலை வழு நீக்கி  மூலம் ஆராய்ச்சி செய்யும் பொழுது ஒரு மாறியின் மதிப்பை கண்டுபிடிக்க pp என்ற கட்டளையை கையாளவேண்டும்; இது pretty-print, அழுபடித்து அச்சிடு என்ற செயலின் ஆங்கில சொற்றொடரின் சுறுக்கமாக pp என்றபடி அமைத்தது; இதன் செயல்பாட்டின் வழியாக மாறியின் மதிப்பை ஒரு pprint  மோட்யூல் வழியாக அச்சிடும். உதாரணம் நமது தற்சமயமாக கையாளும் நிரலின் வழி இதைக்காணலாம்.

(Pdb) pp num_list
[500, 600, 700]
(Pdb) 

pdb இல் உள்ள பல கட்டளைகளுக்கும் முழு கட்டளை பெயரை இடாமல் சற்று குறுகிய வடிவில் (shortcut) தட்டச்சு செய்யலாம்; break என்பதற்கு b, step என்பதற்கு s, next என்றால் n என்றும் எழுதலாம். இதற்குமுன் இட்ட கட்டளை மருஇயக்கம் செய்ய ENTER என்ற விசை தட்டினால் போதும்.

நிறுத்தங்கள் (Breakpoints)

பல நூறு எண்கள் கொண்ட ஒரு நிரலினை வரிவரியாக இயக்கியும் ஆலோசனைசெய்யலாம் ஆனால் அதற்கு ஒரு முழு நாள் போய்விடும்; இதனை தவிற்க்கவும், நிரலினில் உள்ள சுவாரசியமான புள்ளிகளை மட்டுமே அலசுவதற்கு break என்ற கட்டளையைக்கொண்டு நிறுத்தப்புள்ளிகளை செயல்படுத்தலாம். அதாவது அவ்வபோது குறிப்பிட்ட நிறுத்தப்புள்ளிகளின்வரை இயக்கம் தொடர்ந்து செல்லும்.

நிறுத்தப்புள்ளிகளுக்கு pdb 1-இல் தொடங்கியவாரு முழு எண்களை (கூடும் வரிசையில்) குறியீடாக வைத்திருக்கும்; ஆகையால் நிறுத்தப்புள்ளிகளை முழு எண்கள் கொண்டும் குறிப்பிடலாம்.

நிறுத்தப்புள்ளிகளைக் குறிப்பிட <நிரல் கோப்பு>:<வரி எண்> என்றபடி குறிப்பிடலாம்:

(Pdb) break looping.py:5
Breakpoint 1 at /Users/sammy/looping.py:5
(Pdb)

கட்டளை clear என்று அளித்து அதன் கேள்விக்கு y என்றும் அடுத்து உள்ளீடு செய்தால் வழு நீக்கியில் அனைத்து நிறுத்தங்களும் அழிக்கப்படும். அடுத்து எங்கு வேண்டுமானாலும், தற்போது ஒரு சார்பின் தொடக்கத்தில் நிறுத்தம் இடலாம்:

(Pdb) break looping.nested_loop
Breakpoint 1 at /Users/sammy/looping.py:5
(Pdb) 

வழு நீக்கியில் அனைத்து நிறுத்தங்களும் அழிக்க கட்டளை clear என்று அளித்து அதன் கேள்விக்கு y என்றும் அடுத்து உள்ளீடு செய்தால் . நிறுத்தம் என்பது நிபந்தனைக்கு இனங்க செயல்படவும் செயற்படுத்தலாம் – உதாரணம்:

(Pdb) break looping.py:7, number > 500
Breakpoint 1 at /Users/sammy/looping.py:7
(Pdb)     

ஒரு நிறுத்தப்புள்ளியில் இருக்கும் பொழுது continue (தொடர்) என்ற கட்டளையை கொடுத்தால், நிபந்தனை மெய்யாகும் வரை அந்த நிறுத்தப்புள்ளி செயல்தவிர்க்கப்படும் – அதாவது இங்கு number என்ற மாறி 500-க்கும் கூடுதலான வகையில் இயங்கும் வரை அது செயல்படாமல் இருக்கும் (வேறு வகையில் சொல்லவேண்டுமானால் number என்ற மாறி 600 என்ற மதிப்பை வெளி மடக்கின் இரண்டாம் சுற்றில் பெரும் பொழுது இந்த நிறுத்தப்புள்ளி செயல்படும்):

(Pdb) continue
500
x
y
z
> /Users/sammy/looping.py(7)nested_loop()
-> print(number)
(Pdb) 

pdb-இல் உள்ள நிறுவப்பட்ட நிறுத்தப்புள்ளிகளை பார்க்க ‘break’ என்ற கட்டளையை அளிக்கவும்:

(Pdb) break
Num Type         Disp Enb   Where
1   breakpoint   keep yes   at /Users/sammy/looping.py:7
    stop only if number > 500
    breakpoint already hit 2 times
(Pdb) 

disable என்ற கட்டளையைக்கொண்டு ஒரு நிறுத்தப்புள்ளியை செயல்தவிர்க்கலாம்:

(Pdb) break looping.py:11
Breakpoint 2 at /Users/sammy/looping.py:11
(Pdb) disable 1
Disabled breakpoint 1 at /Users/sammy/looping.py:7
(Pdb) break
Num Type         Disp Enb   Where
1   breakpoint   keep no    at /Users/sammy/looping.py:7
    stop only if number > 500
    breakpoint already hit 2 times
2   breakpoint   keep yes   at /Users/sammy/looping.py:11
(Pdb) 

enable என்ற கட்டளையைக்கொண்டு ஒரு நிறுத்தப்புள்ளியை செயல்பாட்டிற்கு கொண்டுவரலாம்; clear என்ற கட்டளையினால் நிறுத்தப்புள்ளியை அழித்துவிடலாம்.

(Pdb) enable 1
Enabled breakpoint 1 at /Users/sammy/looping.py:7
(Pdb) clear 2
Deleted breakpoint 2 at /Users/sammy/looping.py:11
(Pdb) 

pdbயின் நிறுத்தப்புள்ளிகள் வழியாக நிரல் இயத்தின் மீது அதிகளவு கட்டுப்பாடு கிடைக்கிறது. நிறுத்தப்புள்ளிகளில் கூடுதல் செயல்பாடுகளானவை, ignore என்ற கட்டளை – இது நிறுத்தப்புள்ளியினுடன் இணைக்கப்பட்ட இணைசெயல்கள்/நிரல்துண்டுகளை அழித்துவிடு; அதேபோல் command என்ற கட்டளை நிறுத்தப்புள்ளியினுடன் சேர்ந்த இணைசெயல்கள்/நிரல்துண்டுகளை குறிப்பிட உதவும் – எ.கா. ‘command 1’ என்று தொடங்கி இணைசெயல்களைக் குறிப்பிட்டு முடிந்தபின் ‘end’ என்று முடிக்கலாம். மேலும் ‘tbreak’ என்ற கட்டளை ‘temporary break’ என்றதன் சுருக்கமாக முதன்முறை மட்டும் நிறுத்தப்புள்ளியை செயல்படுத்தி இரு இயக்கத்தில் பிடிபட்டபின் ‘clear’ என்ற கட்டளையை இதே நிறுத்தப்புள்ளிக்கு தானாக செலுத்திவிடும் தன்மை உடையது; ‘tbreak 3’ என்பது நிரலின் மேலே இயக்கப்பட்டது.

உங்கள் நிரல்களில் pdb-ஐ இணைப்பது

உங்கள் நிரல்களில் வழுநீக்கம் தானாக நிரல் செயல்பாட்டின் இடையேயும் தொட்டவைக்கலா; இதனைச்செய்ய pdb module-ஐ இணைத்தும் pdb சார்பான pdb.set_trace() என்ற நிரல்பாகம் குறிப்பிட்டிருக்க வேண்டும்; இயக்கம் இந்த நிரல் வரிக்கு வரும்பொழுது உங்கள் நிரலின் இயக்கத்தினிடையே வழு நீக்கி தொடக்கமாகிவிடும்.

உதாரணமாக, நமது மாதிரி நிரலில் (கீழே கொடுக்கப்பட்டது) import வாக்கியத்தின் மூலம் pdb-யின் set_trace சார்பினை அழைக்கவும். நமது உதாரணத்தில், இந்த வழு நீக்கம் சார்பை அடுக்கு மடக்கு வாக்கியதின் (nested loop) முன் சேர்த்துப் பரிசோதனை செய்யலாம்.

# Import pdb module
import pdb

num_list = [500, 600, 700]
alpha_list = ['x', 'y', 'z']

def nested_loop():
    for number in num_list:
        print(number)

        # வழு நீக்கி இங்கு தொடங்கும்
        pdb.set_trace()
        for letter in alpha_list:
            print(letter)

if __name__ == '__main__':
    nested_loop()

இந்த பத்தியில் காட்டியபடி உங்கள் நிரலில் இருந்தபடியே வழு நீக்கியை இணைத்தால் தனிப்பட்டபடி pdb-ஐ இணைக்கவும் வேண்டாம், நிறுத்தப்புள்ளிகளும் தேவையில்லை.

அதாவது pdb module வழியாக அழைக்கப்பட்ட pdb.set_trace() சார்பு உங்கள் நிரலில் எங்கு இங்குகிறதோ அதே இடத்தில் அந்த நிரல் வழு நீக்கியினில் செயல்படும்.

நிரல் இயக்கத்தை மாற்றுவது

Python pdb கட்டளை jump வழியாக இயங்கும் நேரத்தில் ஒரு நிரலின் இயக்கத்தை திசைமாற்றலாம். இதன் மூலம் ஒரு நிரலில் உள்ள சில நிரல்பாகங்களை முன் – பின் வரிசை மாற்றியும் செயல்படுத்தலாம்.

இந்த பகுதியில் sammy (நிரலில் "sammy") என்ற சரத்தில் உள்ள எழுத்துக்களை ஒரு பட்டியலாக பெருவதற்கு நிரல் எழுதுவோம்: letter_list.py

def print_sammy():
    sammy_list = []
    sammy = "sammy"
    for letter in sammy:
        sammy_list.append(letter)
        print(sammy_list)

if __name__ == "__main__":
    print_sammy()

python letter_list.py என்று இயக்கினால், இந்த வெளியீடை பார்க்கலாம் (இது நேர்கோட்டான இயக்கம் – எதுவும் மாற்றங்கள் இல்லாமல் இயக்கப்படுகிறது):

Output['s']
['s', 'a']
['s', 'a', 'm']
['s', 'a', 'm', 'm']
['s', 'a', 'm', 'm', 'y']

அடுத்த முறை இதே நிரலை pdb-யின் மூலம் for மடக்கு வாக்கியதின் இரண்டாம் சுற்றை நீக்கி (நேர்கோட்டற்ற இயக்கத்தின் வழி) இயக்கி பார்க்கலாம்:

python -m pdb letter_list.py

> /Users/sammy/letter_list.py(1)<module>()
-> def print_sammy():
(Pdb) list
  1  -> def print_sammy():
  2         sammy_list = []
  3         sammy = "sammy"
  4         for letter in sammy:
  5             sammy_list.append(letter)
  6             print(sammy_list)
  7     
  8     if __name__ == "__main__":
  9         print_sammy()
 10     
 11     
(Pdb) break 5
Breakpoint 1 at /Users/sammy/letter_list.py:5
(Pdb) continue
> /Users/sammy/letter_list.py(5)print_sammy()
-> sammy_list.append(letter)
(Pdb) pp letter
's'
(Pdb) continue
['s']
> /Users/sammy/letter_list.py(5)print_sammy()
-> sammy_list.append(letter)
(Pdb) jump 6
> /Users/sammy/letter_list.py(6)print_sammy()
-> print(sammy_list)
(Pdb) pp letter
'a'
(Pdb) disable 1
Disabled breakpoint 1 at /Users/sammy/letter_list.py:5
(Pdb) continue
['s']
['s', 'm']
['s', 'm', 'm']
['s', 'm', 'm', 'y']

மேல்கண்டதில் வழுநீக்கி வரி 5-இல் ஒரு நிறுத்தப்புள்ளியை இடுகிறது; இதனை அடைந்த பின் letter என்ற மாறியின் சேமிக்கப்பட்ட மதிப்பை அச்சிடுகிறது. அடுத்தபடியாக, pdb கருவியில், jump கட்டளையைக்கொண்டு வரி 6-இல் நேர்கோட்டுக்கு மாறாக இயக்கத்தை வரி 5-ஐ கடந்து செல்கிறோம். அதாவது மாறி letter-ஐ 'a' என்ற மதிப்பு கொண்டுள்ளது ஆனால் இது பட்டியலில் சேர்க்காமல் வரி 5-ஐ தாவி வரி 6-இல் இயக்கம் தொடர்ந்து செல்கிறது.

இதன்பின் வரி 5-இல் உள்ள நிறுத்தப்புள்ளியை செயல்தவிர்த்து பழையபடியே நிரல் உள்ளவடிவில் இயக்கம் முடிவடைகிறது.

அடுத்து நாம் நிரலில் இயக்கம் முடிந்த ஒருவரிக்கு மீண்டும் இயக்கத்தை திருப்பிச் செல்ல jump  கட்டளையைக் கொண்டு முயற்சிக்கலாம். இந்தமுறை for வாக்கியத்தின் முதல் சுற்றை மீண்டும் pdb-யில் இயக்கிப்பார்க்கலாம்.

> /Users/sammy/letter_list.py(1)<module>()
-> def print_sammy():
(Pdb) list
  1  -> def print_sammy():
  2         sammy_list = []
  3         sammy = "sammy"
  4         for letter in sammy:
  5             sammy_list.append(letter)
  6             print(sammy_list)
  7     
  8     if __name__ == "__main__":
  9         print_sammy()
 10     
 11     
(Pdb) break 6
Breakpoint 1 at /Users/sammy/letter_list.py:6
(Pdb) continue
> /Users/sammy/letter_list.py(6)print_sammy()
-> print(sammy_list)
(Pdb) pp letter
's'
(Pdb) jump 5
> /Users/sammy/letter_list.py(5)print_sammy()
-> sammy_list.append(letter)
(Pdb) continue
> /Users/sammy/letter_list.py(6)print_sammy()
-> print(sammy_list)
(Pdb) pp letter
's'
(Pdb) disable 1
Disabled breakpoint 1 at /Users/sammy/letter_list.py:6
(Pdb) continue
['s', 's']
['s', 's', 'a']
['s', 's', 'a', 'm']
['s', 's', 'a', 'm', 'm']
['s', 's', 'a', 'm', 'm', 'y']

இந்த மேல் காட்டப்பட்ட வழுநீக்கத்தில் வரி-6 இல் முதல் நிறுத்தப்புள்ளி இருக்கிறது; இது வரி 5-ஐ கடந்து செல்கிறது. ஆனாலும் வரி 5-ஐ மீண்டும் நாம் இயக்கச்செய்கின்றோம். இதனால் மாறி ‘letter’ இல் உள்ள மதிப்பான 's' இரண்டு முறை பட்டியலில் இணைக்கப்படுகிறது.

pdb-இல் அனைத்து வரிகளுக்கும் jump கட்டளையைக்கொண்டு நகர்த்திச்செல்ல முடியாது; குறிப்பாக, try:except வாக்கியங்கள், finally வாக்கியங்கள் போன்றவற்றின் இடையிலும், இயக்கத்தை தாவிச்செல்ல முடியாது.

அதாவது jump கட்டளையானது pdb என்பதினைக்கொண்டு ஒரு நிரலின் இயக்கத்தினை திசைமாற்றியும் அதனில் உள்ள வழுக்களை முன்னுக்குப்பின் அலசி ஆராய்ந்து புரிதல் செய்ய உதவும்.

பொதுவான pdb கட்டளைகள்

கீழ்கண்டதாவது பொதுவான pdb கட்டளைகள், அவற்றின் சுறுக்கமான வடிவங்கள், மற்றும் கட்டளை செயல்பாட்டினைப்பற்றிய விளக்கங்கள்.  மேலும் விரிவான pdb பற்றிய தகவல்களுக்கு pdb மூல ஆவணத்தை இங்கு படிக்கலாம்.

கட்டளைசுறுக்கம்விளக்கம்
argsaநிரல்பாகம் சார்பின் உள்ளீடுகளை (function arguments) அச்சிடும்
breakbஇயங்கும் செயலியில் ஒரு நிறுத்தப்புள்ளியை உறுவாக்கும்
continuec or contநிரல் இயக்கத்தை நிறுத்தப்புள்ளியில் இருந்து மீண்டும் தொடங்கச்செய்யும்
helphpdb இல் உள்ள அனைத்து கட்டளைகளையும் உதவிக்குறிப்புகளுடன் காட்டும்
jumpjஅடுத்த நிரல் வரி எடு என்பதை நாம் குறிப்பிட உதவும் கட்டளை
listlஇயக்கப்புள்ளியைச்சுற்றி அமைந்துள்ள நிரல் வரிகளை காட்டும்
nextnநிரல் இயக்கத்தை நிறுத்தப்புள்ளியில் இருந்து சார்பின் அடுத்த வரிக்கு அல்லது அதன் முடிவடையும் வரை நகர்த்திச்செல்லும்.
stepsநிரல் இயக்கத்தை நிறுத்தப்புள்ளியில் இருந்து தொடங்கி அடுத்த நெருக்கமான இடத்தின் வரையில் நிறுத்தம் செய்யும்
ppppநிரலின் ஏதேனும் மாறியின் மதிப்பினை அழகாக அச்சிடும்
quit or exitqநிரல் இயக்கத்தை திடீர் என நிறுத்திதம் செய்யும் அல்லது வெளியேரும்
returnrநிரல் இயக்கத்தை நிறுத்தப்புள்ளியில் இருந்து வெளியேறும்
pdb – பொதுவான கட்டளைகள்

முடிவுரை

வழுநீக்கம் என்பது எந்த ஒரு கணினி நிரலாக்க திட்டத்திற்கும் முக்கியமானது. பைத்தான் மொழியில் pdb என்ற ஒரு வழு நீக்கி செயலி மூலம் பைத்தான் மொழியில் எழுதிய நிரல்களுக்கு ஒரு வழுநீக்கம் செய்யும் சூழலை அளிக்கிறது.

வழுநீக்கி அம்சங்கள் வழியாக இயங்கிக்கொண்டிருக்கும் நிரல்களை நிறுத்தி பரிசோதிக்கலாம், மாறிலிகளின் (variables) மதிப்புகளை பார்க்கலாம், மூல நிரலின் வரிகளில் படிப்படியாக செயலியின் இயக்கத்தை பார்க்கலாம், செயலியின் முழு செயல்பாட்டை புரிந்து கொள்ளலாம், இயக்கத்தில் தர்க்கரீதியான பிழைகள் இருப்பதை கண்டுபிடிக்கலாம் அல்லது முன்கூட்டியே அறிந்த வழுக்களை நீக்கம்செய்ய விசாரணைகள் நடத்தலாம்.

அடிக்குறிப்பு: வழு நீக்கம் சம்பந்தமான தொழில்நுட்பத்தினை தமிழில் எழுதும் முதல் கட்டுரைகளில் இந்த கட்டுரை இடம் பெர வேண்டும் என்பது எனது குறிக்கோள்.

An Introduction to Tamil Computing

இன்று கொரொனா காலத்தில் ஒரு இணையவழி நேரலையில் தமிழ்க்கணிமையில் எப்படி செயல்படுவது என்பதைப்பற்றிய ஒரு அறிமுகப்படுத்தி பேச வாய்ப்பு கிடைத்தது. அழைப்புவிடுத்த பேரா. சுபலலிதா அவர்களுக்கு நன்றி.

காட்சிக்கோப்புகள் இங்கு.

-முத்து

எழில் கணினி நிரலாக்கம் – பயிற்சிப்பட்டறை – மீள்பார்வை

2017-இல் ஒரு பயிற்சிப்பட்டறைக்காக உருவாக்கப்பட்ட காட்சிகோப்புகள் – இதனை கணினி நிரலாக்கம் பயிலவேண்டுமானவர்கள் கண்டிப்பாக படிக்கலாம். மத்தபடி இந்த பட்டறை மாநாட்டில் நடந்ததா என்ற கதையை நீங்கள் எனக்கு ஒரு பீர்/காப்பி (இடம்-பொருள்-நேரம்) எல்லாம் பொருத்து கட்டவிழ்த்து விடுகிறேன். அதுவரை பார்த்து/படித்து மகிழவும்.

எழில் – சில அம்சங்கள் – மீள்பார்வை

சமிபத்தில் எழில் முக்கிய அம்சங்கள் பற்றி பேச நேர்ந்தது. அதன் காட்சிவில்லை.