Выборочная повторная памятка фреймов данных
Скажем, я настроил памятку с Joblib следующим образом (используя решение, представленное здесь):
from tempfile import mkdtemp
cachedir = mkdtemp()
from joblib import Memory
memory = Memory(cachedir=cachedir, verbose=0)
@memory.cache
def run_my_query(my_query)
...
return df
И скажи, что я определил пару запросов, query_1
а также query_2
, оба они занимают много времени, чтобы бежать.
Я понимаю, что с кодом как есть:
Второй вызов с любым запросом будет использовать запомненный вывод, то есть:
run_my_query(query_1) run_my_query(query_1) # <- Uses cached output run_my_query(query_2) run_my_query(query_2) # <- Uses cached output
Я мог бы использовать
memory.clear()
удалить весь каталог кеша
Но что если я захочу заново сделать памятку только для одного из запросов (например, query_2
) без принудительного удаления по другому запросу?
2 ответа
Похоже, библиотека не поддерживает частичное стирание кеша.
Вы можете разделить кеш functino на две пары:
from tempfile import mkdtemp
from joblib import Memory
memory1 = Memory(cachedir=mkdtemp(), verbose=0)
memory2 = Memory(cachedir=mkdtemp(), verbose=0)
@memory1.cache
def run_my_query1()
# run query_1
return df
@memory2.cache
def run_my_query2()
# run query_2
return df
Теперь вы можете выборочно очистить кеш:
memory2.clear()
ОБНОВЛЕНИЕ после просмотра комментария behzad.nouri:
Ты можешь использовать call
метод декорированной функции. Но, как вы можете видеть в следующем примере, возвращаемое значение отличается от обычного вызова. Вы должны позаботиться об этом.
>>> import tempfile
>>> import joblib
>>> memory = joblib.Memory(cachedir=tempfile.mkdtemp(), verbose=0)
>>> @memory.cache
... def run(x):
... print('called with {}'.format(x)) # for debug
... return x
...
>>> run(1)
called with 1
1
>>> run(2)
called with 2
2
>>> run(3)
called with 3
3
>>> run(2) # Cached
2
>>> run.call(2) # Force call of the original function
called with 2
(2, {'duration': 0.0011069774627685547, 'input_args': {'x': '2'}})
Прошло несколько лет, но если ваш код позволяет выполнить рефакторинг на отдельные функции, вы можете легко вызвать
func.clear()
чтобы выборочно удалить эту функцию из кеша.
Пример кода:
#!/usr/bin/env python
import sys
from shutil import rmtree
import joblib
cachedir = "joblib-cache"
memory = joblib.Memory(cachedir)
@memory.cache
def foo():
print("running foo")
return 42
@memory.cache
def oof():
print("running oof")
return 24
def main():
rmtree(cachedir)
print(f"{sys.version=}")
print(f"{joblib.__version__=}")
print(foo())
print(oof())
print()
print("*" * 20 + " These should now be cached " + "*" * 20)
print(foo())
print(oof())
print()
foo.clear()
print("*" * 20 + " `foo` should now be recaculated " + "*" * 20)
print(foo())
print(oof())
if __name__ == "__main__":
main()
Выход:
sys.version='3.9.6 (default, Jun 30 2021, 10:22:16) \n[GCC 11.1.0]'
joblib.__version__='1.0.1'
________________________________________________________________________________
[Memory] Calling __main__--tmp-tmp.DaQHHlsA2H-clearcache.foo...
foo()
running foo
______________________________________________________________foo - 0.0s, 0.0min
42
________________________________________________________________________________
[Memory] Calling __main__--tmp-tmp.DaQHHlsA2H-clearcache.oof...
oof()
running oof
______________________________________________________________oof - 0.0s, 0.0min
24
******************** These should now be cached ********************
42
24
WARNING:root:[MemorizedFunc(func=<function foo at 0x7f9cd7d8e040>, location=joblib-cache/joblib)]: Clearing function cache identified by __main__--tmp-tmp/DaQHHlsA2H-clearcache/foo
******************** `foo` should now be recaculated ********************
________________________________________________________________________________
[Memory] Calling __main__--tmp-tmp.DaQHHlsA2H-clearcache.foo...
foo()
running foo
______________________________________________________________foo - 0.0s, 0.0min
42
24