API Virus Total - ошибка 'Object' object has no attribute 'last_analysis_stats'

Написал код для теста:

import vt
client = vt.Client("token")
print(1)
with open("C:\942079353.jpg", "rb") as f:
    analysis = client.scan_file(f, wait_for_completion=True)
file = client.get_object("/files/44d88612fea8a8f36de82e1278abb02f")
client.close()
print(type(file), 1)
print(type(analysis), 2)
try:
    print(file.last_analysis_stats, 1)
except AttributeError as e:
    print(e, 1)
try:
    print(analysis.last_analysis_stats, 2)
except AttributeError as e:
    print(e, 2)

Получаю такой вывод:

1
<class 'vt.object.Object'> 1
<class 'vt.object.Object'> 2
{'malicious': 67, 'suspicious': 0, 'undetected': 5, 'harmless': 0, 'timeout': 0, 'confirmed-timeout': 0, 'failure': 0, 'type-unsupported': 7} 1
'Object' object has no attribute 'last_analysis_stats' 2

Process finished with exit code 0

Два одинаковых класса, но метода такого нет. Почему?

Вот документация. И даже в ней написано Now file is an instance of vt.Object that contains information about the requested file. Но получить инфу я не могу.


Ответы (1 шт):

Автор решения: mrgervant

Быстрый ответ: print(analysis.stats)

Полный ответ: Классы одинаковые, а атрибуты в них нет. Если заглянуть в документацию или в код библиотеки, то можно увидеть, что class Object:

This class encapsulates any type of object in the VirusTotal API.

То есть, может быть несколько типов объектов, которые будут созданы в рамках одного и того же класса Object. Только по разному - при создании экземпляра класса атрибуты выставляются динамически исходя из наполнения obj_attributes:

if obj_attributes:
    for attr, value in obj_attributes.items():
        setattr(self, attr, value)

Если пройтись по вызовам функций, то в async def _response_to_object можно понять, что obj_attributes формируется из json_response от VirusTotal API - вот и выходит разное наполнение объектов.

Как указано внутри class Object в комментариях к __init__ (вольный перевод):

Инициализируем атрибуты объекта теми, которые входят в obj_attributes, таким образом, если obj_attributes содержит {'foo': 'somevalue'}, вы можете получить доступ к атрибуту как obj.foo, и он вернет 'somevalue'

Вы можете вывести список всех атрибутов через:

print(file.__dict__)
print(analysis.__dict__)

И увидеть, что у каждого из них свой тип ('_type': 'file' и '_type': 'analysis') и, соответственно, свои атрибуты. В частности, у объекта типа analysis нет искомого атрибута last_analysis_stats - есть просто stats (что выводит аналогичный словарь):

{'malicious': 0, 'suspicious': 0, 'undetected': 64, 'harmless': 0, 'timeout': 0, 'confirmed-timeout': 0, 'failure': 1, 'type-unsupported': 14}
→ Ссылка