Это часть моего сценария резервного копирования, который я разделил для тестирования. Это использовалось для работы в python 3.6, но я получаю ошибки в python 3.7. Я проверил документы, но не могу понять, что изменилось.
#! /usr/bin/python
import os
import tarfile
import arrow
stmp = arrow.now().format('YYYY-MM-DD')
backup_path = "/home/akya/playground/"
###########################################################
# Functions
###########################################################
def exclude_function(filename):
if filename in exclude_files or os.path.splitext(filename)[1] in exclude_files:
return True
else:
return False
def compress():
with tarfile.open(myfile, "w:gz") as tar:
for name in L:
tar.add(name, filter=exclude_function)
path1 = "/home/akya/playground/test"
backup_name = "test-"
L = [path1]
exclude_files = [".sh", ".html", ".json", "/home/akya/playground/test/.git"]
myfile = str(backup_path + backup_name + stmp + ".tar.gz")
compress()
Я хочу, чтобы tarfile исключал любые расширения и пути в exclude_files. и это то, что я получаю
Traceback (most recent call last):
File "exec.py", line 33, in <module>
compress()
File "exec.py", line 24, in compress
tar.add(name, filter=exclude_function)
File "/usr/lib/python3.7/tarfile.py", line 1934, in add
tarinfo = filter(tarinfo)
File "exec.py", line 16, in exclude_function
if filename in exclude_files or os.path.splitext(filename)[1] in exclude_files:
File "/usr/lib/python3.7/posixpath.py", line 122, in splitext
p = os.fspath(p)
TypeError: expected str, bytes or os.PathLike object, not TarInfo
Может ли кто-нибудь указать на необходимость изменения? или лучший способ использования фильтров?
Обратный вызов filter
передает структуру TarInfo
вашему TarInfo
вызову, поэтому вы можете фильтровать что-то другое, кроме имени: дата, размер, время модификации (очень похоже на объект stat
)...
Кроме того, это не работает (возвращая логические значения), вы должны вернуть None
если хотите исключить эту запись:
TarFile.add(name, arcname = None, recursive = True, *, filter = None)
... Если задан фильтр, он должен быть функцией, которая принимает аргумент объекта TarInfo и возвращает измененный объект TarInfo. Если он вместо этого возвращает None, объект TarInfo будет исключен из архива. См. Примеры для примера.
В вашем случае просто выберите поле .name
и верните None
если это соответствует вашему фильтру. Else возвращает ту же структуру tarinfo
вы получили.
def exclude_function(tarinfo):
filename = tarinfo.name
return None if filename in exclude_files or os.path.splitext(filename)[1] in exclude_files else tarinfo
(обратите внимание, что я не знаю, почему это сработало для вас в более ранних версиях, возможно, вы добавили это or os.path.splitext(filename)[1] in exclude_files
что показывает, что тип неверен - первый in
тесте wouldn ' t сбой даже с объектом неправильного типа - но это правильный способ сделать это)