Tekst funkcji przetwarzania wstępnego w kompilacji czasu wykonywania
Postanowiłem przetworzyć tekst funkcji przed kompilacją na kod bajtowy i po wykonaniu. To jest tylko trening. Nie wyobrażam sobie sytuacji, w których byłoby to zadowalające rozwiązanie. Stałem wobec jednego problemu, który chciałem rozwiązać w ten sposób, ale w końcu znaleziono lepszy sposób. To jest tylko trening i nauczenie się czegoś nowego, a nie do prawdziwego użycia.
Załóżmy, że mamy funkcję, którą kod źródłowy chcemy zmodyfikować przed kompilacją:
def f():
1;a()
print('Some statements 1')
1;a()
print('Some statements 2')
Pozwól, na przykład, oznaczyć niektóre jego linie1;
, aby były czasem komentowane, a czasami nie. Po prostu biorę to na przykład, modyfikacje funkcji mogą być inne.
Aby skomentować te wiersze, zrobiłem dekoratora. Cały kod, który poniżej:
from __future__ import print_function
def a():
print('a()')
def comment_1(s):
lines = s.split('\n')
return '\n'.join(line.replace(';','#;',1) if line.strip().startswith('1;') else line for line in lines)
def remove_1(f):
import inspect
source = inspect.getsource(f)
new_source = comment_1(source)
with open('temp.py','w') as file:
file.write(new_source)
from temp import f as f_new
return f_new
def f():
1;a()
print('Some statements 1')
1;a()
print('Some statements 2')
f = remove_1(f) #If decorator @remove is used above f(), inspect.getsource includes @remove inside the code.
f()
użyłeminspect.getsourcelines odzyskać funkcjęf
kod. Potem zrobiłem trochę przetwarzania tekstu (w tym przypadku linie komentowania zaczynające się od1;
). Po tym zapisałem gotemp.py
moduł, który jest następnie importowany. A potem funkcjaf
jest ozdobiony w głównym module.
Wyjście, gdy zastosowany jest dekorator, jest następujące:
Some statements 1
Some statements 2
gdy NIE jest stosowany, to:
a()
Some statements 1
a()
Some statements 2
Nie podoba mi się to, że muszę używać dysku twardego do ładowania skompilowanej funkcji. Czy można to zrobić bez zapisywania go w module tymczasowymtemp.py
i importować z niego?
Drugie pytanie dotyczy umieszczenia dekoratora powyżejf
: @replace
. Kiedy to robię,inspect.getsourcelines
zwracaf
tekst z tym dekoratorem. Mogłem zostać ręcznie usunięty zf
tekst. ale to byłoby dość niebezpieczne, ponieważ może być zastosowanych więcej niż jeden dekorator. Dlatego skorzystałem ze składni dekoracji w starym styluf = remove_1(f)
, która wykonuje pracę. Ale nadal możliwe jest zastosowanie normalnej techniki dekoracji@replace
?