Вот такой вот класс:
import ctypes
class CMagic:
__mgc = None
__cookie = None
def __init__(self):
#Загружаем libmagic.so
self.__mgc = ctypes.cdll.LoadLibrary("libmagic.so")
#Создаем новый cookie (требуется для
#работы с magic-последовательностями)
#0x10 | 0x400 = MAGIC_MIME (константа
#декларируется в magic.h)
self.__cookie = self.__mgc.magic_open(0x10 | 0x400)
#Загружаем в __cookie
#/etc/file/magic.mime (т.к. указано None)
self.__mgc.magic_load(self.__cookie, None)
def __del__(self):
#Закрываем __cookie
self.__mgc.magic_close(self.__cookie)
def getMType(self,filename):
#Получаем информацию о файле
result = self.__mgc.magic_file(self.__cookie,filename)
#magic_file возвращает const char*,
#mimetype.value - это строка по указателю
mimetype = ctypes.c_char_p(result)
rez = mimetype.value
return rez
def is_video(self,filename):
#Проверяем, является ли файл
#- видео файлом
mime = self.getMType(filename)
if mime.count("video"):
return 1
return 0
4 комментария:
ИМХО, если уж завязываться на платформозависимые вещи, то можно было сделать проще используя file и popen2:
import popen2, string
cout,cin=popen2.popen2('file file1.txt file2.txt')
lines=cout.readlines()
d=dict([ [ i.strip() for i in l.split(':',1) ] for l in lines ])
получив словарик
{'file1.txt': 'ASCII text', 'file2.txt': 'ASCII text'}
В корне своем решения у нас одинаковые - и там, и там libmagic.so пользуется (у вас - в утилите file).
С точки зрения простоты кода - вы выиграли :-)
С точки зрения применения - выигрывает класс, ибо писался он для создания огромного плейлиста по моей кинотеке - а у меня там еще и музыка намешана и другой мусор - для ~2000 файлов накладно 2000 раз создавать дочерний процесс, имхо. (Хотя нужно сравнить)
Мой вариант использования libmagic через вызов file не только компактнее, но менее хрупок и легче модифицируем.
Например, код в вашем примере у меня не заработает, а бросит исключение OSError, потому что в _моей_ системе, библиотека называется libmagic.so.1, а не libmagic.so… Обращение к file эти тонкости маскирует. Всё же python — это не си и не си++. Опять же, если нужно получать типы в формате mime-type, то с file достаточно добавить "-i". Нужен специальный magic-file — тоже просто. Минус моего варианта — надо квотировать пробелы и спецсимволы в именах файлов.
По поводу запуска новых процессов, то в unix они достаточно лёгкие, и это традиционный способ программирования. Кроме того, можно сразу просить определить типы нескольких файлов — так что запусков нового процесса нужно меньше, чем количество файлов.
Кстати, вот маленький тест:
Music$ time find . -iname '*.mp3' -print0 | xargs -0 -n 1 file -i >/dev/null
real 0m24.198s
user 0m7.356s
sys 0m1.304s
Music$ time find . -iname '*.mp3' -print0 | xargs -0 -n 500 file -i >/dev/null
real 0m22.774s
user 0m6.888s
sys 0m0.380s
— определяется тип для 1050 файлов, разница между 1050 запусками file и 3 запусками пренебрежимо мала по сравнению с временем, которое ему нужно, чтобы заглянуть в каждый из 1050 файлов, и может быть объяснена кэшированием файловой системы. Время работы find в одиночку 0.978s. Кстати, любопытно, сколько времени на это уйдёт, если использовать libmagic напрямую. Я предполагаю, что на таком наборе файлов разница не превысит 15%.
pyxdg вам поможет
Отправить комментарий