Меню

Pip install exif ошибка

Те, кто знает Python, могут делать поистине удивительные вещи, например, создавать арт-объекты и игры и красивые карты, полнотекстовую поисковую машину и систему распознавания лиц. Применим Python и для вполне бытовых задач. Сегодня, специально к старту новых потоков курсов Python для веб-разработки и Fullstack-разработчик на Python поделимся с вами туториалом, как считывать, добавлять и удалять EXIF метаданные из фотографий с помощью Python.


Немного очевидного для тех кто не в теме — метаданные в фото

Массовое распространение смартфонов (по сути, портативных, оснащённых датчиками, всегда подключённых к сети компьютеров) привело к двум важным последствиям — влиянию на конфиденциальность и влиянию на безопасность, и это ещё не до конца изучено:

  1. У большого количества людей есть камера, которая обычно находится в пределах досягаемости.

  2. По умолчанию фотографии, сделанные на  камеру, могут выдавать конфиденциальную информацию, и многие пользователи не подозревают об этом.

Помимо данных изображения фотографии, сделанные с помощью смартфонов и современных цифровых камер, содержат метаданные, которые являются дополнительной информацией о фотографии. Эти метаданные хранятся в формате EXIF (сокращение от EXchangeable Image File format), который является постоянно развивающимся стандартом для информации, добавляемой к цифровым изображениям и звукозаписям.

На фотографиях EXIF ​​может включать такую ​​информацию, как:

  • Размеры и плотность пикселей фото.

  • Марка и модель устройства, на котором был сделан снимок.

  • Масштабирование, диафрагма, вспышка и другие настройки камеры при съёмке фотографии.

  • Ориентация устройства при фотографировании.

  • Когда было сделано фото.

  • Где было сделано фото.

  • В каком направлении была обращена камера.

  • Высота, на которой был сделан снимок.

Эти метаданные полезны для сортировки, каталогизации и поиска фотографий, поэтому был определён стандарт EXIF. Однако при этом возникают проблемы с конфиденциальностью и безопасностью, которые многие пользователи не принимают во внимание.

Одним из первых предостережений об EXIF ​​является инцидент с конфиденциальностью в 2012 году, связанный с основателем антивирусной компании Джоном Макафи. Это было захватывающее время в жизни Макафи, поскольку он уклонялся от действий правоохранительных органов, но при этом давал журналистам эксклюзивные, пользующиеся большим спросом интервью. Один журналист, которому посчастливилось взять интервью, решил похвастаться своей удачей, опубликовав фотографию Макафи, но предварительно не удалив EXIF-данные. Они и раскрыли местонахождение Макафи и привели к его аресту.

Вы, вероятно, знаете о недавних историях, когда правоохранительные органы арестовывали подозреваемых, используя фотографии, размещённые в социальных сетях, потому что подозреваемые не принимали меры предосторожности и не «очищали» свои данные EXIF ​​в процессе загрузки.

Я подозреваю, что вы как разработчики, заботящиеся о безопасности, вероятно, задаёте себе следующие вопросы:

  • Как я могу программно обнаружить и прочитать EXIF-метаданные ​​с фотографии?

  • Как я могу программно изменять, добавлять или удалять EXIF-метаданные?

Если на вашем компьютере установлен Python 3.6 или более поздней версии, вы можете узнать это, выполнив приведённые ниже инструкции. Они охватывают пару пакетов Python, которые вы можете включить в свои приложения для извлечения, добавления, изменения или удаления EXIF-данных ​​с фотографий. Попутно вы не только будете использовать свои навыки программирования, но и поработаете детективом!

Модуль exif

Существует ряд модулей Python, которые могут получить доступ к данным EXIF ​​в цифровых фотографиях. В этой статье мы сосредоточимся на exif. Его API настолько питонический, что кажется, будто он является частью языка, а не модулем.

Чтобы установить exif, используйте pip, введя в командной строке следующее:

pip install exif

Если при вводе этой команды выдаётся сообщение об ошибке, попробуйте вместо этого использовать команду pip3 install exif. pip3 — это версия pip, менеджера пакетов Python, специально предназначенная для Python 3.

Если вы не поддерживаете какой-либо код на Python 2, но вам нужно использовать pip3 для установки пакетов Python, то вам следует подумать об обновлении Python.

Загрузка фотографий и проверка их на наличие данных EXIF

Давайте проверим exif в работе. Рассмотрим эти две фотографии, palmtree1.jpg и palmtree2.jpg:

Предположим, вам задали следующие вопросы:

  1. Были ли эти фотографии сделаны на одно устройство или на разные?

  2. Какое фото было сделано первым?

  3. Где были сделаны эти фотографии?

Чтобы ответить на эти вопросы, мы загрузим данные из этих фотографий в объекты exif-Image, а затем будем использовать эти объекты для проверки EXIF-метаданных:

from exif import Image

with open("./images/palm tree 1.jpg", "rb") as palm_1_file:
    palm_1_image = Image(palm_1_file)
    
with open("./images/palm tree 2.jpg", "rb") as palm_2_file:
    palm_2_image = Image(palm_2_file)
    
images = [palm_1_image, palm_2_image]

Код открывает каждый файл только для чтения. Он считывает данные файла в двоичном формате в объект файла, который затем используется для создания экземпляра объекта exif-Image. Наконец, он помещает объекты Image в массив, чтобы мы могли перебирать их, выполняя одни и те же операции с EXIF-метаданными каждой фотографии.

Давайте выполним нашу первую операцию: убедимся, что фото действительно содержат EXIF-данные. Мы сделаем это, проверив свойство has_exif каждого объекта Image. Для каждого изображения, содержащего EXIF-данные, мы будем использовать свойство изображения exif_version, чтобы отобразить версию EXIF:

for index, image in enumerate(images):
    if image.has_exif:
        status = f"contains EXIF (version {image.exif_version}) information."
    else:
        status = "does not contain any EXIF information."
    print(f"Image {index} {status}")

При запуске этот код даёт следующие результаты:

Image 0 contains EXIF (version 0220) information.
Image 1 contains EXIF (version 0232) information.

Теперь мы знаем, что обе фотографии содержат информацию EXIF ​​и используют разные версии EXIF. Скорее всего, эти фотографии были сделаны на разные камеры.

Какие метаданные EXIF ​​доступны на каждой фотографии?

Думайте о EXIF ​​как о структуре данных «ключ-значение», подобной словарю Python. Пары «ключ-значение» EXIF ​​называются тегами, и каждый тег может содержать строковое или числовое значение. В текущем стандарте EXIF ​​(версия 2.32) есть десятки тегов, и каждый — от производителей смартфонов и камер до фотографов — может добавлять свои собственные теги.

Вот полный список тегов EXIF, которые вы, вероятно, найдёте на цифровых фотографиях. Кроме того, тут есть теги, не входящие в стандарт EXIF, но предоставляемые рядом устройств или программного обеспечения.

EXIF — один из тех неформальных форматов, где производители сами выбирают, какие функции они будут реализовывать. Это означает, что фотографии, снятые разными камерами и смартфонами, будут иметь разные наборы тегов EXIF.

Как правило, вы можете рассчитывать на то, что смартфоны встраивают в фотографии, ряд часто используемых тегов EXIF, включая марку и модель смартфона, дату и время, когда была сделана фотография, место, где она была сделана, общие сведения и настройки камеры.

Учитывая различия между устройствами и наличие инструментов для редактирования данных EXIF, первое, что вы должны сделать при работе с EXIF данными ​​фотографии, — это посмотреть, какие теги доступны.

Объекты Image, предоставляемые модулем exif, представляют теги EXIF ​​как свойства этого объекта. Это означает, что вы можете использовать встроенную функцию Python dir() для объекта Image, чтобы увидеть, какие теги EXIF ​​у него есть.

Следующий код отображает список тегов каждого объекта Image в нашем списке изображений:

image_members = []

for image in images:
    image_members.append(dir(image))

for index, image_member_list in enumerate(image_members):
    print(f"Image {index} contains {len(image_member_list)} members:")
    print(f"{image_member_list}n")

Вы увидите следующий результат:

Image 0 contains 53 members:
['_exif_ifd_pointer', '_gps_ifd_pointer', '_segments', 'aperture_value', 'brightness_value', 'color_space', 'components_configuration', 'datetime', 'datetime_digitized', 'datetime_original', 'delete', 'delete_all', 'digital_zoom_ratio', 'exif_version', 'exposure_bias_value', 'exposure_mode', 'exposure_program', 'exposure_time', 'f_number', 'flash', 'flashpix_version', 'focal_length', 'focal_length_in_35mm_film', 'get', 'get_file', 'get_thumbnail', 'gps_altitude', 'gps_altitude_ref', 'gps_datestamp', 'gps_latitude', 'gps_latitude_ref', 'gps_longitude', 'gps_longitude_ref', 'has_exif', 'light_source', 'make', 'max_aperture_value', 'metering_mode', 'model', 'orientation', 'photographic_sensitivity', 'pixel_x_dimension', 'pixel_y_dimension', 'resolution_unit', 'scene_capture_type', 'sensing_method', 'shutter_speed_value', 'subsec_time', 'subsec_time_digitized', 'subsec_time_original', 'white_balance', 'x_resolution', 'y_resolution']

Image 1 contains 68 members:
['<unknown EXIF tag 316>', '<unknown EXIF tag 322>', '<unknown EXIF tag 323>', '<unknown EXIF tag 42080>', '_exif_ifd_pointer', '_gps_ifd_pointer', '_segments', 'aperture_value', 'brightness_value', 'components_configuration', 'datetime', 'datetime_digitized', 'datetime_original', 'delete', 'delete_all', 'exif_version', 'exposure_bias_value', 'exposure_mode', 'exposure_program', 'exposure_time', 'f_number', 'flash', 'flashpix_version', 'focal_length', 'focal_length_in_35mm_film', 'get', 'get_file', 'get_thumbnail', 'gps_altitude', 'gps_altitude_ref', 'gps_dest_bearing', 'gps_dest_bearing_ref', 'gps_horizontal_positioning_error', 'gps_img_direction', 'gps_img_direction_ref', 'gps_latitude', 'gps_latitude_ref', 'gps_longitude', 'gps_longitude_ref', 'gps_speed', 'gps_speed_ref', 'has_exif', 'lens_make', 'lens_model', 'lens_specification', 'make', 'maker_note', 'metering_mode', 'model', 'offset_time', 'offset_time_digitized', 'offset_time_original', 'orientation', 'photographic_sensitivity', 'pixel_x_dimension', 'pixel_y_dimension', 'resolution_unit', 'scene_capture_type', 'scene_type', 'sensing_method', 'shutter_speed_value', 'software', 'subject_area', 'subsec_time_digitized', 'subsec_time_original', 'white_balance', 'x_resolution', 'y_resolution']

Как вы можете видеть, в то время как оба объекта Image имеют много общих тегов, изображение 1 содержит немного больше, чем изображение 0. Это означает, что изображение 1 имеет несколько больше тегов EXIF, чем изображение 0. Это сильный индикатор того, что изображение 0 и изображение изображение 1 было снято на разные устройства.

Вы можете использовать стандартный метод set() для определения общих элементов изображения 0 и изображения 1:

common_members = set(image_members[0]).intersection(set(image_members[1]))
common_members_sorted = sorted(list(common_members))
print("Image 0 and Image 1 have these members in common:")
print(f"{common_members_sorted}")

Запуск этого кода даёт следующий результат:

Image 0 and Image 1 have these members in common:
['_exif_ifd_pointer', '_gps_ifd_pointer', '_segments', 'aperture_value', 'brightness_value', 'components_configuration', 'datetime', 'datetime_digitized', 'datetime_original', 'delete', 'delete_all', 'exif_version', 'exposure_bias_value', 'exposure_mode', 'exposure_program', 'exposure_time', 'f_number', 'flash', 'flashpix_version', 'focal_length', 'focal_length_in_35mm_film', 'get', 'get_file', 'get_thumbnail', 'gps_altitude', 'gps_altitude_ref', 'gps_latitude', 'gps_latitude_ref', 'gps_longitude', 'gps_longitude_ref', 'has_exif', 'make', 'metering_mode', 'model', 'orientation', 'photographic_sensitivity', 'pixel_x_dimension', 'pixel_y_dimension', 'resolution_unit', 'scene_capture_type', 'sensing_method', 'shutter_speed_value', 'subsec_time_digitized', 'subsec_time_original', 'white_balance', 'x_resolution', 'y_resolution']

Если вы смотрели EXIF-теги в документации (либо список стандартных тегов EXIF, либо расширенный список), вы могли заметить, что имена тегов EXIF находятся в PascalCase, а свойства EXIF в объектах exif-Image — в snake_case. Это связано с тем, что авторы модуля exif стремятся следовать руководству по стилю Python и разработали Image для преобразования имён тегов EXIF в имена свойств Python.

Члены класса Image exif, не являющиеся тегами EXIF

Большинство членов класса любых экземпляров изображения будут свойствами, соответствующими тегам EXIF в изображении. Однако есть несколько членов для работы с метаданными EXIF. Они перечислены в таблице ниже:

Члены класса

Описание

delete(attribute)

Удаляет из изображения тег EXIF, указанный в строковом атрибуте.

delete_all

Удаляет все теги EXIF из изображения.

get(attribute, default=None)

Возвращает значение тега EXIF, заданное строковым атрибутом. Если тег недоступен или содержит значение, он возвращает значение, указанное в аргументе ключевого слова по умолчанию.

get_file

Возвращает текущие данные изображения, отформатированные для записи в двоичный файл.

get_thumbnail

Возвращает двоичные данные для эскиза изображения.

has_exif

Логическое значение, которое возвращает True, если изображение в настоящее время содержит метаданные EXIF.

set(attribute, value)

Установить значение для тега EXIF, заданное строковым атрибутом. Если тег недоступен или содержит значение, он возвращает значение, указанное в аргументе ключевого слова по умолчанию.

В этой статье мы рассмотрим большинство из этих свойств и методов.

Получение основной информации о фотографиях

Ответим на первый вопрос об этих фотографиях. Были ли они сняты на одно устройство или на разные? У нас уже есть основания полагать, что ответ — «нет».

Марка и модель устройства, на котором было сделано фото.

У обоих изображений есть теги марки и модели, поэтому давайте с их помощью определим, какие устройства использовались для создания этих снимков:

for index, image in enumerate(images):
    print(f"Device information - Image {index}")
    print("----------------------------")
    print(f"Make: {image.make}")
    print(f"Model: {image.model}n")

Вот результат кода выше:

Device information - Image 0
----------------------------
Make: motorola
Model: motorola one hyper

Device information - Image 1
----------------------------
Make: Apple
Model: iPhone 12 Pro

Это подтверждает, что фотографии были сделаны на разных устройствах, и теперь мы знаем детали.

Дополнительная информация об устройствах

Давайте соберём дополнительную информацию об устройствах, которые используются для фотосъёмки, а именно об их объективах и версиях операционной системы.

Не все устройства сообщают тип линзы в своих EXIF-метаданных, поэтому мы будем использовать метод Image get(), который аналогичен методу get(), используемому в Python. Подобно методу get() в Python, метод get(), предоставляемый объектом exif Image, изящно обрабатывает случай, когда данный ключ не существует.

В приведённом ниже коде используется get(), чтобы попытаться получить доступ к версиям объектива и операционной системы, используемым при съёмке фотографий. Если определённого свойства не существует, его значение будет отображаться как «Неизвестно»:

for index, image in enumerate(images):
    print(f"Lens and OS - Image {index}")
    print("---------------------")
    print(f"Lens make: {image.get('lens_make', 'Unknown')}")
    print(f"Lens model: {image.get('lens_model', 'Unknown')}")
    print(f"Lens specification: {image.get('lens_specification', 'Unknown')}")
    print(f"OS version: {image.get('software', 'Unknown')}n")

Вот его результат:

Lens and OS - Image 0
---------------------
Lens make: Unknown
Lens model: Unknown
Lens specification: Unknown
OS version: Unknown

Lens and OS - Image 1
---------------------
Lens make: Apple
Lens model: iPhone 12 Pro back triple camera 4.2mm f/1.6
Lens specification: (1.5399999618512084, 6.0, 1.6, 2.4)
OS version: 14.3

Обратите внимание, что телефон, используемый для съёмки изображения 0 (Motorola One Hyper), не предоставляет свойства lens_make, lens_model, lens_specification или software. Если бы мы попытались получить к ним доступ напрямую (например, image.lens_make), результатом была бы ошибка. Метод get() позволил нам предоставить альтернативное значение для этих несуществующих свойств.

Дата и время, когда была сделана фотография

Следующий вопрос: какое фото было сделано первым?

Мы можем узнать это, просмотрев свойство datetime_original каждой фотографии, которое указывает на дату и время, когда фотография была сделана. Процессор смартфона достаточно быстр, чтобы записывать точную долю секунды, когда он делает фотографию, и это значение сохраняется в свойстве subsc_time_original.

Некоторые телефоны также записывают свойство offset_time, которое мы можем использовать для определения смещения datetime относительно UTC.

Следующий код отображает дату и время, когда была сделана каждая из фотографий. Если фотография включает данные о временном сдвиге, код также отобразит это значение:

for index, image in enumerate(images):
    print(f"Date/time taken - Image {index}")
    print("-------------------------")
    print(f"{image.datetime_original}.{image.subsec_time_original} {image.get('offset_time', '')}n")

Вот результаты:

Date/time taken - Image 0
-------------------------
2021:01:22 15:08:46.327211 

Date/time taken - Image 1
-------------------------
2021:01:22 15:08:59.383 -05:00

Как видно из вывода, изображение 0 было снято первым, а изображение 1 было снято через 13 секунд.

Определение места, где была сделана фотография

В этом разделе мы рассмотрим доступ к GPS-координатам в метаданных фотографии, форматирование этих координат и упрощение понимания этих координат путём их размещения на карте и преобразования их в названия страны, региона и города, где фото было сделано.

Получение GPS-координат фотографии

Формат EXIF определяет ряд тегов, начинающихся с «gps», которые содержат полезную информацию о геолокации, включая широту и долготу, где была сделана фотография:

for index, image in enumerate(images):
    print(f"Coordinates - Image {index}")
    print("---------------------")
    print(f"Latitude: {image.gps_latitude} {image.gps_latitude_ref}")
    print(f"Longitude: {image.gps_longitude} {image.gps_longitude_ref}n")

Вот результат кода выше:

Coordinates - Image 0
---------------------
Latitude: (28.0, 0.0, 1.56) N
Longitude: (82.0, 26.0, 59.04) W

Coordinates - Image 1
---------------------
Latitude: (28.0, 0.0, 1.54) N
Longitude: (82.0, 26.0, 58.75) W

Обратите внимание, что свойства gps_latitude и gps_longitude возвращают широту и долготу в виде кортежа из трёх значений:

  1. Градусы.

  2. Минуты (1/60 градуса).

  3. Секунды (1/60 минуты или 1/3600 градуса).

Широта определяет угловое расстояние от экватора, которое может быть северным или южным. Свойство gps_latitude_ref указывает это направление, которое может быть N или S.

Долгота определяет угловое расстояние от меридиана, которое может быть восточным или западным. Свойство gps_longitude_ref указывает это направление: E или W.

Возможно, вы заметили небольшую разницу между координатами, указанными на фотографиях. Это ожидаемо: даже одно и то же устройство, расположенное в одном месте, в разное время будет сообщать немного разные координаты. Расхождение в координатах, сообщаемых телефонами, составляет порядка долей секунды, что соответствует примерно 25 футам или 7,6 метрам.

Форматирование широты и долготы

Давайте определим пару функций для форматирования информации о широте и долготе, возвращаемой Image, в стандартные форматы:

  • Градусы, минуты и секунды. В этом формате широта изображения 0 будет записана как 28.0 ° 0.0 ‘1.56 «N.

  • Десятичные градусы. В этом формате широта изображения 0 будет записана как 28,000433333333334. Северные широты и восточные долготы представлены положительными значениями, в то время как южные широты и западные долготы представлены отрицательными значениями.

Вот определения этих функций, а также некоторый код, который их использует:

def format_dms_coordinates(coordinates):
    return f"{coordinates[0]}° {coordinates[1]}' {coordinates[2]}""

def dms_coordinates_to_dd_coordinates(coordinates, coordinates_ref):
    decimal_degrees = coordinates[0] + 
                      coordinates[1] / 60 + 
                      coordinates[2] / 3600
    
    if coordinates_ref == "S" or coordinates_ref == "W":
        decimal_degrees = -decimal_degrees
    
    return decimal_degrees

for index, image in enumerate(images):
    print(f"Coordinates - Image {index}")
    print("---------------------")
    print(f"Latitude (DMS): {format_dms_coordinates(image.gps_latitude)} {image.gps_latitude_ref}")
    print(f"Longitude (DMS): {format_dms_coordinates(image.gps_longitude)} {image.gps_longitude_ref}n")
    print(f"Latitude (DD): {dms_coordinates_to_dd_coordinates(image.gps_latitude, image.gps_latitude_ref)}")
    print(f"Longitude (DD): {dms_coordinates_to_dd_coordinates(image.gps_longitude, image.gps_longitude_ref)}n")

Вот результат:

Coordinates - Image 0
---------------------
Latitude (DMS): 28.0° 0.0' 1.56" N
Longitude (DMS): 82.0° 26.0' 59.04" W

Latitude (DD): 28.000433333333334
Longitude (DD): -82.44973333333334

Coordinates - Image 1
---------------------
Latitude (DMS): 28.0° 0.0' 1.54" N
Longitude (DMS): 82.0° 26.0' 58.75" W

Latitude (DD): 28.000427777777777
Longitude (DD): -82.44965277777779

Отображение местоположения фотографий на карте

Вы, вероятно, не знаете широту и долготу своего дома, даже если округлить до ближайшего градуса. Есть несколько простых способов преобразовать данные о местоположении EXIF во что-то более лёгкое для понимания.

Один из способов — использовать встроенный в Python модуль webbrowser для открытия новой вкладки браузера для каждой фотографии, используя десятичную версию EXIF-координат каждой фотографии в качестве параметров URL-адреса Google Maps. Мы создадим служебную функцию с именем draw_map_for_location(), которая сделает следующее:

def draw_map_for_location(latitude, latitude_ref, longitude, longitude_ref):
    import webbrowser
    
    decimal_latitude = dms_coordinates_to_dd_coordinates(latitude, latitude_ref)
    decimal_longitude = dms_coordinates_to_dd_coordinates(longitude, longitude_ref)
    url = f"https://www.google.com/maps?q={decimal_latitude},{decimal_longitude}"
    webbrowser.open_new_tab(url)

for index, image in enumerate(images):
    draw_map_for_location(image.gps_latitude, 
                          image.gps_latitude_ref, 
                          image.gps_longitude,
                          image.gps_longitude_ref)

Когда вы запустите его, откроются две новые вкладки браузера, на каждой из которых будет отображаться карта Google, указывающая, где была сделана соответствующая фотография.

Отображение города, региона и страны, где был сделан снимок

Другой способ отобразить местоположение фотографии — использовать обратное геокодирование, то есть процесс преобразования географических координат в адрес или название места. Для этого нам нужно установить два модуля Python:

  • reverse_geocoder — простой автономный обратный геокодер, который использует внутренние таблицы для преобразования набора координат в набор названий городов и штатов/провинций и кодов стран. Установите его, введя pip install reverse_geocoder в командной строке.

  • pycountry — утилита поиска стран, которую мы будем использовать для преобразования кодов стран в их соответствующие названия. Установите это, введя pip install pycountry в командной строке.

После того как вы установили указанные выше модули, используйте следующий код, чтобы преобразовать координаты фотографии в нечто более узнаваемое:

import reverse_geocoder as rg
import pycountry

for index, image in enumerate(images):
    print(f"Location info - Image {index}")
    print("-----------------------")
    decimal_latitude = dms_coordinates_to_dd_coordinates(image.gps_latitude, image.gps_latitude_ref)
    decimal_longitude = dms_coordinates_to_dd_coordinates(image.gps_longitude, image.gps_longitude_ref)
    coordinates = (decimal_latitude, decimal_longitude)
    location_info = rg.search(coordinates)[0]
    location_info['country'] = pycountry.countries.get(alpha_2=location_info['cc'])
    print(f"{location_info}n")

В коде используется метод search() из reverse_geocoder для преобразования десятичных значений широты и долготы каждой фотографии в набор следующей информации:

  • Название города, посёлка или деревни.

  • Главный административный регион, который обычно представляет собой штат или провинцию.

  • Незначительный административный район, который обычно является округом или районом.

  • Код страны.

Затем он использует метод get() из pycountry для преобразования кода страны, предоставленного reverse_geocoder, в кортеж, содержащий соответствующие общие и официальные названия стран.

Вот его результат:

Location info - Image 0
-----------------------
{'lat': '27.94752', 'lon': '-82.45843', 'name': 'Tampa', 'admin1': 'Florida', 'admin2': 'Hillsborough County', 'cc': 'US', 'country': Country(alpha_2='US', alpha_3='USA', name='United States', numeric='840', official_name='United States of America')}

Location info - Image 1
-----------------------
{'lat': '27.94752', 'lon': '-82.45843', 'name': 'Tampa', 'admin1': 'Florida', 'admin2': 'Hillsborough County', 'cc': 'US', 'country': Country(alpha_2='US', alpha_3='USA', name='United States', numeric='840', official_name='United States of America')}

Другая полезная информация о датчиках

Как я уже упоминал в начале этой статьи, смартфоны снабжены датчиками. К ним относятся магнитометр, барометр и акселерометр. В сочетании с GPS эти датчики предоставляют дополнительную информацию, которая добавляется к метаданным EXIF каждой фотографии.

В каком направлении была обращена камера?

Магнитометр воспринимает магнитные поля, в том числе создаваемые Землёй. Его основная цель — быть компасом телефона и определять направление, на которое он указывает. Эта информация записывается в EXIF в виде компасного курса каждый раз, когда вы делаете снимок.

Давайте определим, в каком направлении я смотрел, когда делал каждую из этих фотографий:

Мы будем использовать следующие свойства exif-Image, чтобы определить направление, в котором была направлена камера:

  • gps_img_direction: направление по компасу, то есть направление, в котором смотрела камера, когда был сделан снимок, выраженный в десятичных градусах. 0 ° — север, 90 ° — восток, 180 ° — юг и 270 ° — запад.

  • gps_img_direction_ref: контрольная точка для gps_img_direction. Это может быть либо T, что означает, что 0° относится к истинному или географическому северу, либо M, что означает, что 0 ° относится к магнитному северу. В большинстве случаев используется истинный север.

В приведённом ниже коде показано направление камеры для четырёх фотографий озера. Он использует несколько служебных функций:

  • degrees_to_direction(): эта функция преобразует направления по компасу в основные направления (например, N, NE, NNE и т. д.);

  • format_direction_ref(): эта функция превращает значение в gps_img_direction_ref  понятную для человека строку.

def degrees_to_direction(degrees):
    COMPASS_DIRECTIONS = [
        "N",
        "NNE",
        "NE",
        "ENE",
        "E", 
        "ESE", 
        "SE", 
        "SSE",
        "S", 
        "SSW", 
        "SW", 
        "WSW", 
        "W", 
        "WNW", 
        "NW", 
        "NNW"
    ]
    
    compass_directions_count = len(COMPASS_DIRECTIONS)
    compass_direction_arc = 360 / compass_directions_count
    return COMPASS_DIRECTIONS[int(degrees / compass_direction_arc) % compass_directions_count]

def format_direction_ref(direction_ref):
    direction_ref_text = "(true or magnetic north not specified)"
    if direction_ref == "T":
        direction_ref_text = "True north"
    elif direction_ref == "M":
        direction_ref_text = "Magnetic north"
    return direction_ref_text

# Import images
lake_images = []
for i in range(1, 5):
    filename = f"lake {i}.jpg"
    with open(f"./images/{filename}", "rb") as current_file:
        lake_images.append(Image(current_file))

# Display camera direction for each image
for index, image in enumerate(lake_images):
    print(f"Image direction - Image {index}")
    print("-------------------------")
    print(f"Image direction: {degrees_to_direction(image.gps_img_direction)} ({image.gps_img_direction}°)")
    print(f"Image direction ref: {format_direction_ref(image.gps_img_direction_ref)}n")

Когда вы запустите код, вы увидите следующий результат:

Image direction - Image 0
-------------------------
Image direction: ENE (78.416259765625°)
Image direction ref: True north

Image direction - Image 1
-------------------------
Image direction: N (1.174224853515625°)
Image direction ref: True north

Image direction - Image 2
-------------------------
Image direction: SSE (178.46739196870607°)
Image direction ref: True north

Image direction - Image 3
-------------------------
Image direction: W (273.8248136315229°)
Image direction ref: True north

На какой высоте был сделан снимок?

В дополнение к предоставлению координат местоположения GPS также может использоваться для определения высоты. Некоторые смартфоны оснащены барометрами (которые определяют давление воздуха), которые они используют для повышения точности измерения высоты.

Давайте выясним, на каких высотах были сделаны эти фотографии:

Мы воспользуемся этими свойствами объекта Exif Image для определения высоты:

  • gps_altitude: высота в метрах;

  • gps_altitude_ref: контрольная точка для gps_altitude. Это значение равно 0, что означает, что значение в gps_altitude относится к метрам над уровнем моря, или 1, что означает, что значение в gps_altitude относится к метрам ниже уровня моря.

Следующий код отображает высоту, сообщённую телефоном в момент съёмки каждой из фотографий. Он использует одну служебную функцию, format_altitude(), которая определяет, находится ли заданная высота над или под уровнем моря:

def format_altitude(altitude, altitude_ref):
    altitude_ref_text = "(above or below sea level not specified)"
    if altitude_ref == 0:
        altitude_ref_text = "above sea level"
    elif altitude_ref == 1:
        altitude_ref_text = "below sea level"
    return f"{altitude} meters {altitude_ref_text}"

# Import images
altitude_images = []
for i in range(1, 3):
    filename = f"altitude {i}.jpg"
    with open(f"./images/{filename}", "rb") as current_file:
        altitude_images.append(Image(current_file))
        
# Display camera altitude for each image
for index, image in enumerate(altitude_images):
    print(f"Altitude - Image {index}")
    print( "------------------")
    print(f"{format_altitude(image.gps_altitude, image.gps_altitude_ref)}n")

Вот результат:

Altitude - Image 0
------------------
14.025835763206075 meters above sea level

Altitude - Image 1
------------------
359.13079847908745 meters above sea level

Я мог бы сказать вам, где я сделал эти фотографии, но вы уже знаете, как это выяснить.

Двигался ли фотограф?

Смартфоны используют комбинацию местоположений GPS с течением времени и акселерометра, чтобы определить скорость телефона и направление, в котором он движется. Некоторые телефоны предоставляют эту информацию как часть метаданных EXIF на фотографиях.

Мой Motorola One Hyper не записывает метаданные, связанные со скоростью, но мой iPhone это делает. Доступ к этим данным можно получить с помощью этих двух методов объекта exif Image:

  • gps_speed: скорость, выраженная в виде числа;

  • gps_speed_ref: единицы скорости, используемые для значения в gps_speed. Это значение может быть: K — для километров в час; M — для миль в час; N — для морских миль в час, или «узлов».

Рассмотрим следующие фото:

Вот код, который выводит записанную скорость во время съёмки каждой фотографии. Он включает функцию универсальности, format_speed_ref(), которая определяет единицы сообщаемой скорости:

def format_speed_ref(speed_ref):
    speed_ref_text = "(speed units not specified)"
    if speed_ref == "K":
        speed_ref_text = "km/h"
    elif speed_ref == "M":
        speed_ref_text = "mph"
    elif speed_ref == "N":
        speed_ref_text = "knots"
    return speed_ref_text

# Import images
speed_images = []
for i in range(1, 4):
    filename = f"speed {i}.jpg"
    with open(f"./images/speed {i}.jpg", "rb") as current_file:
        speed_images.append(Image(current_file))
    
for index, image in enumerate(speed_images):
    print(f"Speed - Image {index}")
    print("---------------")
    print(f"Speed: {image.gps_speed} {format_speed_ref(image.gps_speed_ref)}n")

Вот результат:

Speed - Image 0
---------------
Speed: 0.0 km/h

Speed - Image 1
---------------
Speed: 20.19736291335287 km/h

Speed - Image 2
---------------
Speed: 5.520932607215793 km/h

Редактирование EXIF данных и их сохранение

Пока что мы ограничились простым чтением метаданных EXIF с фотографий. Следующим шагом является внесение изменений в эти данные, а затем сохранение результатов в виде нового файла фотографии.

Редактирование координат фотографии

Начнём с этой фотографии:

К настоящему времени вы должны знать, как читать координаты из EXIF и использовать эти координаты, чтобы открыть карту Google, чтобы показать местоположение, где фото снято.

Вот код, который это сделает. Он использует служебную функцию draw_map_for_location(), которую мы определили ранее:

with open(f"./images/hotel original.jpg", "rb") as hotel_file:
    hotel_image = Image(hotel_file)
    
# Read the GPS data
print("Original coordinates")
print("--------------------")
print(f"Latitude: {hotel_image.gps_latitude} {hotel_image.gps_latitude_ref}")
print(f"Longitude: {hotel_image.gps_longitude} {hotel_image.gps_longitude_ref}n")

# Open a Google Map showing the location represented by these coordinates
draw_map_for_location(hotel_image.gps_latitude,
                      hotel_image.gps_latitude_ref,
                      hotel_image.gps_longitude,
                      hotel_image.gps_longitude_ref

Он выводит следующее:

Original coordinates
--------------------
Latitude: (28.0, 21.0, 58.44) N
Longitude: (81.0, 33.0, 34.29) W

Кроме того, он открывает новую вкладку браузера, показывающую карту Google, которая отображает отели Swan и Dolphin, которые находятся в нескольких минутах ходьбы от Walt Disney World во Флориде.

Давайте сделаем вещи немного интереснее, изменив координаты, встроенные в данные EXIF ​​фотографии, чтобы они сообщали, что она была сделана в Зоне 51. Если вы не слышали об этом месте, это военный объект в Неваде, в котором, как считают теоретики теории заговора, правительство США хранит тела пришельцев и космический корабль, захваченные в 1950-х годах. Его координаты: 37,0 ° 14 ‘3,6 «северной широты, 115 ° 48’ 23,99» западной долготы.

Вы видели, что чтение значения тега EXIF ​​с использованием объекта Exif Image — это просто чтение значения в соответствующем свойстве. Точно так же редактирование его значения — это просто вопрос присвоения нового значения этому свойству. В этом случае мы присвоим значения, определяющие координаты Зоны 51, свойствам изображения gps_latitude, gps_latitude_ref, gps_longitude и gps_longitude_ref:

# Boring. Let's change those coordinates to Area 51!
hotel_image.gps_latitude = (37.0, 14, 3.6)
hotel_image.gps_latitude_ref = 'N'
hotel_image.gps_longitude = (115, 48, 23.99)
hotel_image.gps_longitude_ref = 'W'

# Read the revised GPS data
print("Revised coordinates")
print("-------------------")
print(f"Latitude: {hotel_image.gps_latitude} {hotel_image.gps_latitude_ref}")
print(f"Longitude: {hotel_image.gps_longitude} {hotel_image.gps_longitude_ref}n")

# Open a Google Map showing the location represented by the revised coordinates
draw_map_for_location(hotel_image.gps_latitude,
                      hotel_image.gps_latitude_ref,
                      hotel_image.gps_longitude,
                      hotel_image.gps_longitude_ref

Выполнение кода приведёт к следующему результату …

Revised coordinates
-------------------
Latitude: (37.0, 14.0, 3.6) N
Longitude: (115.0, 48.0, 23.99) W

… и он откроет новую вкладку с картой Google, в которой отображается Зона 51.

Заполнение неиспользуемых тегов EXIF

В текущей спецификации EXIF ​​определено множество тегов, и большинство камер заполняют лишь небольшую их часть. Модуль exif позволяет заполнять любые теги EXIF, которым не присвоено значение.

Примечание: модуль exif записывает только теги в спецификации EXIF, но не дополнительные теги, включённые поставщиками. «Официальные» теги в спецификации EXIF ​​подчёркнуты.

Вы можете присвоить значение тегу вне спецификации EXIF, даже тегу, который вы создали. Объект Image будет хранить это значение, но только до тех пор, пока объект остаётся в памяти. Вы не сможете сохранять теги, отличные от EXIF, или их значения, потому что метод, преобразующий данные в объекте Image для записи в файл, учитывает только стандартные теги EXIF.

Вот несколько тегов EXIF, которые вы, возможно, захотите заполнить, так как они удобны для управления библиотекой фотографий. Они оба принимают строковые значения:

  • ImageDescription: описание фотографии. В объектах Exif Image это отображается как свойство image_description.

  • Copyright: уведомление об авторских правах на фотографию. В объектах Exif Image это свойство copyright.

Вот код, который заполняет эти теги:

hotel_image.image_description = "The Dolphin Hotel in Orlando, viewed at sunset from the Swan Hotel"
hotel_image.copyright = "Copyright 2021 (Your name here)"

print(f"Description: {hotel_image.image_description}")
print(f"Copyright: {hotel_image.copyright}")

Выполнение кода даёт следующий результат:

Description: The Dolphin Hotel in Orlando, viewed at sunset from the Swan Hotel
Copyright: Copyright 2021 (Your name here)

Сохранение фото с обновленными данными

Теперь, когда мы отредактировали данные EXIF на картинке, давайте сохраним их как новый файл с названием hotel_updated.jpg.

with open('./images/hotel updated.jpg', 'wb') as updated_hotel_file:
    updated_hotel_file.write(hotel_image.get_file())

Этот код создаёт файловый объект updated_hotel_file для записи двоичных данных в файл с именем hotel_updated.jpg. Затем он использует метод Image get_file() для получения данных об изображении отеля в сериализуемой форме и записывает эти данные в файл.

Теперь у вас должен быть новый файл: hotel_updated.jpg. Загрузим его и убедимся, что изменённые и добавленные данные сохранены:

with open(f"./images/hotel updated.jpg", "rb") as hotel_file:
    hotel_image = Image(hotel_file)
    
print("Coordinates")
print("-----------")
print(f"Latitude: {hotel_image.gps_latitude} {hotel_image.gps_latitude_ref}")
print(f"Longitude: {hotel_image.gps_longitude} {hotel_image.gps_longitude_ref}n")

print("Other info")
print("----------")
print(f"Description: {hotel_image.image_description}")
print(f"Copyright: {hotel_image.copyright}")

# Open a Google Map showing the location represented by these coordinates
draw_map_for_location(hotel_image.gps_latitude,
                      hotel_image.gps_latitude_ref,
                      hotel_image.gps_longitude,
                      hotel_image.gps_longitude_ref

Код выдаст вам этот результат …

Coordinates
-----------
Latitude: (37.0, 14.0, 3.6) N
Longitude: (115.0, 48.0, 23.99) W

Other info
----------
Description: The Dolphin Hotel in Orlando, viewed at sunset from the Swan Hotel
Copyright: Copyright 2021 (Your name here)

… и откроется ещё одна вкладка браузера, отображающая Зону 51 на карте.

Удаление данных EXIF и сохранение «очищенной» фотографии

Предположим, что вместо изменения данных о местоположении на фотографии отеля мы решили удалить теги. Есть два способа сделать это.

Первый способ — использовать метод delete(), предоставляемый объектом Exif-Image. Давайте используем его, чтобы удалить данные о широте:

hotel_image.delete('gps_latitude')
hotel_image.delete('gps_latitude_ref')

print("Latitude data")
print("-------------")
print(f"gps_latitude: {hotel_image.get('gps_latitude', 'Not found')}")
print(f"gps_latitude_ref: {hotel_image.get('gps_latitude_ref', 'Not found')}")

Вот результат кода выше:

Latitude data
-------------
gps_latitude: Not found
gps_latitude_ref: Not found

Второй способ — использовать оператор Python del, который удаляет объекты из памяти. В этом случае мы будем использовать его для удаления атрибутов hotel_image, в которых хранятся данные о долготе:

del hotel_image.gps_longitude
del hotel_image.gps_longitude_ref

print("Longitude data")
print("--------------")
print(f"gps_longitude: {hotel_image.get('gps_longitude', 'Not found')}")
print(f"gps_longitude_ref: {hotel_image.get('gps_longitude_ref', 'Not found')}")

Вот результат кода выше:

Longitude data
--------------
gps_longitude: Not found
gps_longitude_ref: Not found

Теперь, когда мы удалили данные о местоположении с фотографии, давайте сохраним её под новым именем, hotel_without_location_data.jpg:

with open('./images/hotel without location data.jpg', 'wb') as updated_hotel_file:
    updated_hotel_file.write(hotel_image.get_file())

Наконец, если вы хотите просто удалить все данные EXIF с фотографии, вы можете использовать метод delete_all() объекта exif Image:

hotel_image.delete_all()

dir(hotel_image)
['<unknown EXIF tag 322>',
 '<unknown EXIF tag 323>',
 '_segments',
 'delete',
 'delete_all',
 'get',
 'get_file',
 'get_thumbnail',
 'has_exif']

Опять же, как только вы использовали delete_all() для удаления всех тегов EXIF, вам нужно сохранить эти изменения. Приведённый ниже код сохраняет наше изображение со всеми удалёнными тегами как hotel_without_tags.jpg:

with open('./images/hotel without tags.jpg', 'wb') as updated_hotel_file:
    updated_hotel_file.write(hotel_image.get_file())

Практические и технические соображения

Причины удаления метаданных EXIF

Метаданные EXIF ​​добавляют к цифровым фотографиям совершенно новый уровень информации и ряд вещей, которые необходимо учитывать пользователям, разработчикам и организациям.

Одно из очевидных соображений — это конфиденциальность. Метаданные GPS для отдельной фотографии могут определить ваше местоположение в определённую дату и время. Что гораздо более ценно, так это совокупный GPS из чьей-то камеры, поскольку он содержит шаблоны, которые можно проанализировать, чтобы определить, где вы живёте, работаете и какие места вы часто посещаете в повседневной жизни. Вот почему более авторитетные социальные сети удаляют эту информацию, когда вы публикуете свои фотографии в Интернете. Помните, что это означает лишь то, что ваши фотографии в галерее социальной сети не содержат данных GPS. Нет гарантии, что служба не записала информацию о местоположении чтобы передать её рекламодателю перед её удалением.

Другие метаданные EXIF, такие как марка, модель, настройки и даже ориентация камеры, могут использоваться для связывания набора фотографий с конкретным человеком.

Некоторые фотографы больше озабочены секретностью, чем конфиденциальностью, когда речь идёт о метаданных их фотографий. Они не хотят разглашать настройки камеры, которые использовали для фотосъёмки.

Причины редактирования или добавления метаданных EXIF

Одна из первоначальных причин, по которой был разработан формат метаданных EXIF, заключалась в том, чтобы упростить автоматизацию процесса каталогизации, сортировки и поиска в коллекции цифровых фотографий. EXIF позволяет искать фотографии, сделанные в течение определенного периода, с помощью определённого устройства или в определённом месте. Другие теги, такие как тег copyright, позволяют искать фотографии, сделанные определённым фотографом, а также защищать его авторские права.

Хотя тег ImageDescription был предназначен для хранения описания изображения, вы также можете использовать его для хранения другой полезной текстовой информации, связанной с фотографией, например тегов для классификации изображения или инструкций по обработке и редактированию фотографии.

Метаданные EXIF ​​особенно полезны в мобильных приложениях, которые записывают одновременные комбинации визуальной информации, информации о дате/времени и местоположении. Например, от техника может потребоваться сделать фотографии выполненных ремонтных работ «до» и «после» с указанием того, где, когда и как были выполнены эти работы.

Другие вещи, которые следует учитывать

Как мы видели в различных тегах, записанных устройствами iPhone и Android, используемыми для фотосъёмки в этой статье, разные камеры записывают разные наборы тегов EXIF. Программное обеспечение для редактирования фотографий часто записывает информацию в разные теги или добавляет свои собственные теги. Эти дополнительные метаданные часто могут указывать на то, что фотография была отредактирована.

В фотографии дикой природы существует концепция Ethical EXIF, которая описывает этические стандарты, которым следует придерживаться при съёмке. Он включает такую ​​информацию, как состояние здоровья и уровень стресса животного на фотографии, как долго животное находилось в неволе и было ли животное вывезено из среды обитания для фотографии.

Наконец, есть сообщения, которые отображаются в мобильных приложениях, использующих камеру, при первом использовании. Обычно они говорят что-то вроде «Это приложение использует камеру. Вы согласны? », Но большинство из них не даёт понять, что камера добавляет местоположение и другие метаданные к каждой сделанной фотографии. Если вы пишете мобильные приложения, использующие камеру, вы можете сообщить об этом пользователю.

Знание Python — это полезный hard skill не только для программиста, но и для аналитика и даже маркетолога. С ним вы можете сами написать простой парсер, написать небольшое приложение под свои задачи и даже увеличить свой доход, выполняя заказы на фрилансе. Если вы хотите дополнительно прокачать себя и освоить этот язык под чутким руководством наших опытных менторов — обратите внимание на курс Fullstack-разработчик на Python и Python для веб-разработки.

Узнайте, как прокачаться в других специальностях или освоить их с нуля:

  • Профессия Data Scientist

  • Профессия Data Analyst

  • Курс по Data Engineering

Другие профессии и курсы

https://www.gitlab.com/TNThieding/exif/badges/master/pipeline.svg
https://www.gitlab.com/tnthieding/exif/badges/master/coverage.svg
Documentation Status
https://img.shields.io/badge/code%20style-black-000000.svg
Checked with mypy

Read and modify image EXIF metadata using Python without any third-party software
dependencies. For example, batch process image metadata using a Python script.

Quick Start

Open an image with EXIF metadata using the Python open() built-in function. Ensure the
binary mode flag is set. Pass this image file object into the exif.Image class:

>>> from exif import Image
>>> with open('grand_canyon.jpg', 'rb') as image_file:
...     my_image = Image(image_file)
...
>>> my_image.has_exif
True

List EXIF attributes using the list_all() method:

>>> my_image.list_all()
['_exif_ifd_pointer', '_gps_ifd_pointer', 'aperture_value', 'brightness_value', 'color_space',
 'components_configuration', 'compression', 'datetime', 'datetime_digitized', 'datetime_original', 'exif_version',
 'exposure_bias_value', 'exposure_mode', 'exposure_program', 'exposure_time', 'f_number', 'flash',
 'flashpix_version', 'focal_length', 'focal_length_in_35mm_film', 'gps_altitude', 'gps_altitude_ref',
 'gps_datestamp', 'gps_dest_bearing', 'gps_dest_bearing_ref', 'gps_horizontal_positioning_error',
 'gps_img_direction', 'gps_img_direction_ref', 'gps_latitude', 'gps_latitude_ref', 'gps_longitude',
 'gps_longitude_ref', 'gps_speed', 'gps_speed_ref', 'gps_timestamp', 'jpeg_interchange_format',
 'jpeg_interchange_format_length', 'lens_make', 'lens_model', 'lens_specification', 'make', 'maker_note',
 'metering_mode', 'model', 'orientation', 'photographic_sensitivity', 'pixel_x_dimension', 'pixel_y_dimension',
 'resolution_unit', 'scene_capture_type', 'scene_type', 'sensing_method', 'shutter_speed_value', 'software',
 'subject_area', 'subsec_time_digitized', 'subsec_time_original', 'white_balance', 'x_resolution',
 'y_and_c_positioning', 'y_resolution']

Access EXIF metadata tags using Python attribute notation:

>>> # Read tags with Python "get" notation.
>>> my_image.gps_latitude
(36.0, 3.0, 11.08)
>>> my_image.gps_longitude
(112.0, 5.0, 4.18)
>>> my_image.model
'iPhone 7'
>>>
>>> # Modify tags with Python "set" notation.
>>> my_image.make = "Python"
>>>
>>> # Delete tags with Python "del" notation.
>>> del my_image.gps_latitude
>>> del my_image.gps_longitude
>>>
>>> # Add new tags with Python "set" notation.
>>> from exif import LightSource
>>> my_image.light_source = LightSource.DAYLIGHT

Write the image with modified EXIF metadata to an image file using open() in binary
write mode:

>>> with open('modified_image.jpg', 'wb') as new_image_file:
...     new_image_file.write(my_image.get_file())
...

Refer to the usage page for information and examples of alternative ways to access EXIF tags (e.g.
with index/item syntax or with methods).

Программные пакеты Python устанавливаются и управляются с помощью пакетов установки Pip (pip). Как правило, он используется для пакетов в индексе пакетов Python. Ваша системная переменная PATH должна быть установлена ​​так, чтобы команды Python можно было запускать из командной строки Windows.

Если вы установили Python через установочный файл, он должен добавиться автоматически. Пользователи пакета Python часто получают сообщение об ошибке pip не работает и не знают, как это исправить. Ознакомьтесь с этими советами по устранению этой ошибки, если вы столкнулись с ней.

Питон

Содержание страницы

  • Как исправить установку PIP, не работающую в Windows 10/11

    • Исправление 1: убедитесь, что PIP был добавлен в вашу переменную PATH
    • Исправление 2: добавьте PIP в переменную среды PATH
    • Исправление 3: убедитесь, что Pip включен в установку
    • Исправление 4: переустановите его

Как исправить установку PIP, не работающую в Windows 10/11

Хотя это техническая вещь, вы можете исправить это, даже если у вас почти нет знаний о том, как исправить установку PIP, не работающую на ПК с Windows 10/11. Итак, давайте проверим, как это сделать:

Исправление 1: убедитесь, что PIP был добавлен в вашу переменную PATH

  1. Откройте CMD с правами администратора.
  2. Теперь выполните команду: эхо% ПУТЬ%Убедитесь, что PIP был добавлен в вашу переменную PATH
  3. В зависимости от вашей версии Python вы найдете такой путь, как «C:/Python39/Scripts». Если это так, то путь добавляется, и теперь вы увидите, что установка PIP снова начинает работать.

Исправление 2: добавьте PIP в переменную среды PATH

  1. Откройте окно «Выполнить» и найдите sysdm.cpl чтобы открыть свойства системы.
  2. Теперь переключитесь на Передовой вкладку и нажмите на Переменные среды.
  3. Затем доступ Системные переменные и выберите Дорожка.Добавьте PIP в переменную среды PATH
  4. Теперь нажмите на Редактировать кнопку и нажмите на Новый чтобы добавить путь установки pip. Однако, чтобы добавить путь установки pip, вы должны открыть CMD и выполнить эту команду: setx ПУТЬ «% ПУТЬ%; C:Python39СкриптыДобавьте PIP в переменную среды PATH

Исправление 3: убедитесь, что Pip включен в установку

  1. Откройте страницу настроек Windows и перейдите в Программы раздел.
  2. Затем щелкните правой кнопкой мыши на Питон и ударил Изменять кнопка.
  3. Теперь нажмите на Изменить вариант и под Дополнительные особенности, проверить точка коробка и удар Следующий.
  4. Вот и все. Теперь, чтобы сохранить изменения, нажмите кнопку Установить кнопка.

После этого обязательно перезагрузите компьютер с Windows 10/11 и проверьте, устранена ли ошибка установки PIP, не работающая или нет.

Исправление 4: переустановите его

Эта ошибка обычно возникает из-за проблемы с установкой Python или неправильно настроенной переменной PATH. Чтобы решить эту проблему, переустановите Python и все его компоненты. Использование исполняемого установщика Python — самый простой способ. Вы можете сделать это, выполнив следующие действия:

Объявления

  1. Откройте страницу настроек Windows и перейдите в Программы раздел.
  2. Затем щелкните правой кнопкой мыши на Питон и ударил удалить кнопка.
  3. После этого перезагрузите устройство и снова загрузите Python.
  4. Затем установите его, как обычно, и проверьте, устранена ли ошибка установки PIP, которая не работает.

Итак, это все о том, как исправить установку PIP, не работающую в Windows 10/11. Мы надеемся, что вы найдете это руководство полезным. Между тем, если у вас есть какие-либо сомнения или вопросы, прокомментируйте ниже и дайте нам знать.

Ответ на:

комментарий
от t184256 21.10.19 23:21:23 MSK

не получилось устранить ошибку по поиску в нете.
вот сама ошибка:
Traceback (most recent call last):
File «/usr/bin/pip», line 6, in <module>
from pkg_resources import load_entry_point
ModuleNotFoundError: No module named ‘pkg_resources’

  • Показать ответ
  • Ссылка

Ответ на:

комментарий
от cretin00 21.10.19 23:26:31 MSK

Это модуль из состава setuptools. Есть идеи, как и чем ты сломал setuptools? Переустановить можешь?

t184256 ★★★★★

(21.10.19 23:27:54 MSK)

  • Показать ответы
  • Ссылка

Ответ на:

комментарий
от t184256 21.10.19 23:27:54 MSK

идей нет,сам переставить не смогу.

  • Ссылка

Ответ на:

комментарий
от t184256 21.10.19 23:27:54 MSK

при установке программ python выходят такие ошибки:
предупреждение: не удалось получить информацию о файле для usr/lib/python3.7/site-packages/__pycache__/easy_install.cpython-37.opt-1.pyc
предупреждение: не удалось получить информацию о файле для usr/lib/python3.7/site-packages/__pycache__/easy_install.cpython-37.pyc
предупреждение: не удалось получить информацию о файле для usr/lib/python3.7/site-packages/easy_install.py
предупреждение: не удалось получить информацию о файле для usr/lib/python3.7/site-packages/pkg_resources/
предупреждение: не удалось получить информацию о файле для usr/lib/python3.7/site-packages/pkg_resources/__init__.py
предупреждение: не удалось получить информацию о файле для usr/lib/python3.7/site-packages/pkg_resources/__pycache__/
предупреждение: не удалось получить информацию о файле для usr/lib/python3.7/site-packages/pkg_resources/__pycache__/__init__.cpython-37.opt-1.pyc
предупреждение: не удалось получить информацию о файле для usr/lib/python3.7/site-packages/pkg_resources/__pycache__/__init__.cpython-37.pyc
предупреждение: не удалось получить информацию о файле для usr/lib/python3.7/site-packages/pkg_resources/__pycache__/py31compat.cpython-37.opt-1.pyc
предупреждение: не удалось получить информацию о файле для usr/lib/python3.7/site-packages/pkg_resources/__pycache__/py31compat.cpython-37.pyc
предупреждение: не удалось получить информацию о файле для usr/lib/python3.7/site-packages/pkg_resources/py31compat.py
предупреждение: не удалось получить информацию о файле для usr/lib/python3.7/site-packages/setuptools-41.2.0-py3.7.egg-info/
предупреждение: не удалось получить информацию о файле для usr/lib/python3.7/site-packages/setuptools-41.2.0-py3.7.egg-info/PKG-INFO
предупреждение: не удалось получить информацию о файле для usr/lib/python3.7/site-packages/setuptools-41.2.0-py3.7.egg-info/SOURCES.txt
предупреждение: не удалось получить информацию о файле для usr/lib/python3.7/site-packages/setuptools-41.2.0-py3.7.egg-info/dependency_links.txt
предупреждение: не удалось получить информацию о файле для usr/lib/python3.7/site-packages/setuptools-41.2.0-py3.7.egg-info/entry_points.txt
предупреждение: не удалось получить информацию о файле для usr/lib/python3.7/site-packages/setuptools-41.2.0-py3.7.egg-info/requires.txt
предупреждение: не удалось получить информацию о файле для usr/lib/python3.7/site-packages/setuptools-41.2.0-py3.7.egg-info/top_level.txt
предупреждение: не удалось получить информацию о файле для

  • Показать ответ
  • Ссылка

Ответ на:

комментарий
от cretin00 21.10.19 23:43:21 MSK

В большинстве дистрибутивов Linux pip можно безопасно использовать только в virtualenv или в крайнем случае от пользователя с –user. Запуск pip от root за пределами virtualenv — верный способ заработать конфликты с системным менеджером пакетов. Так что переустанавливай arch полностью.

AEP ★★★★★

(22.10.19 09:14:10 MSK)

  • Показать ответ
  • Ссылка

Ответ на:

комментарий
от ei-grad 22.10.19 09:21:14 MSK

Проблема решается очень просто. Могу рассказать как.

Да, всё верно. Я с таким уже сталкивался и описанный способ мне помог.

anonymous

(22.10.19 09:57:00 MSK)

  • Ссылка

Ответ на:

комментарий
от AEP 22.10.19 09:14:10 MSK

С менеджером пакетов скорее всего нет, потому что pip кладёт в /usr/local даже при обновлении пакетов, которые через системный менеджер установлены, а вот проблем с совместимостью пакетов между собой огрести можно легко. Сам нарывался.

Radjah ★★★★★

(22.10.19 10:42:57 MSK)

  • Показать ответ
  • Ссылка

Ответ на:

комментарий
от t184256 21.10.19 23:50:22 MSK

командой sudo pacman -Rsccdd namep?

  • Ссылка

Ответ на:

комментарий
от ei-grad 22.10.19 09:21:14 MSK

Пипка.

anonymous

(22.10.19 14:14:49 MSK)

  • Ссылка

Ответ на:

комментарий
от Radjah 22.10.19 10:42:57 MSK

С менеджером пакетов скорее всего нет, потому что pip кладёт в /usr/local даже при обновлении пакетов, которые через системный менеджер установлены

Это дистроспецифичный патч. В Debian и Ubuntu это так, в других дистрибутивах — нет.

AEP ★★★★★

(22.10.19 16:04:16 MSK)

  • Ссылка

Всегда используй virtualenv

  • Ссылка

Ответ на:

комментарий
от cretin00 22.10.19 16:12:05 MSK

Ответ на:

комментарий
от t184256 22.10.19 16:15:37 MSK

Ответ на:

комментарий
от cretin00 22.10.19 16:21:07 MSK

Тебе дали пакетный менеджер, со встроенными средствами починки таких проблем между прочим, а ты насоздавал новых, пойдя ему в обход.

t184256 ★★★★★

(22.10.19 16:24:28 MSK)

  • Показать ответ
  • Ссылка

Ответ на:

комментарий
от t184256 22.10.19 16:24:28 MSK

Ответ на:

комментарий
от cretin00 22.10.19 16:12:05 MSK

Но ведь ты не решил проблему с pacman, а до тех пор у тебя система сломана. Сделай pacman -Qkk python-setuptools.

Thetan ★★★

(22.10.19 16:27:29 MSK)

  • Показать ответ
  • Ссылка

Ответ на:

комментарий
от Thetan 22.10.19 16:27:29 MSK

точно,вот выхлоп:
python-setuptools: всего 192 файла, 0 измененных файлов

  • Ссылка

Ответ на:

комментарий
от cretin00 22.10.19 16:26:23 MSK

Ответ на:

комментарий
от t184256 22.10.19 16:33:09 MSK

Ответ на:

комментарий
от t184256 22.10.19 16:15:37 MSK

Ответ на:

комментарий
от cretin00 22.10.19 16:33:47 MSK

https://wiki.archlinux.org/index.php/Python#Package_management

If you must use pip, use a virtual environment, or pip install --user to avoid conflicts with packages in /usr. It is always preferred to use pacman to install software.

https://wiki.archlinux.org/index.php/Python_(Русский)#Управление_пакетами

Если вы собираетесь использовать pip, используйте его в виртуальном окружении или с опцией --user (pip install --user), чтобы избежать конфликтов между пакетами в каталоге /usr. Во всех случаях предпочтительный способ установки программного обеспечения — это использование pacman.

Примечание: Существуют инструменты, автоматически генерирующие PKGBUILDы для пакетов pip и таким образом интегрирующие его в pacman: pipman-git, pip2arch-git

greenman ★★★★★

(22.10.19 17:11:37 MSK)



Последнее исправление: greenman 22.10.19 17:16:31 MSK
(всего

исправлений: 3)

  • Ссылка

Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.

0 / 0 / 0

Регистрация: 25.01.2020

Сообщений: 3

1

25.01.2020, 15:26. Показов 26101. Ответов 12


Не работает pip install в Python 3.8.1
>>> pip install colorama
File «<stdin>», line 1
pip install colorama

SyntaxError: invalid syntax
пишу в cmd, путь в PATH прописан(как и в переменные среды пользователя так и в системных переменных). Помогите пожалуйста!

__________________
Помощь в написании контрольных, курсовых и дипломных работ, диссертаций здесь



0



Programming

Эксперт

94731 / 64177 / 26122

Регистрация: 12.04.2006

Сообщений: 116,782

25.01.2020, 15:26

Ответы с готовыми решениями:

Не работает команда pip
Здравствуйте. Установил я питон на свой компьютер (Версия python 3.8.1). И все было хорошо до того…

Не работает pip
Дароу коллеги, сегодня столкнулся с такой проблемой, что не могу установить библиотеку через pip3….

Не работает Pip
Установил python 3.5.1 с офф. сайта. Ессно, pip установился с ним в комплекте. Но ни в IDLE, ни в…

Не работает PIP
Добрый день!
Подскажите пожалуйста, я только-только начал изучать программу Python и решил…

12

Эксперт Python

5403 / 3827 / 1214

Регистрация: 28.10.2013

Сообщений: 9,554

Записей в блоге: 1

25.01.2020, 15:53

2

Цитата
Сообщение от BobyBorn
Посмотреть сообщение

пишу в cmd

Ты пишешь в консоли Python, а не cmd.



1



0 / 0 / 0

Регистрация: 25.01.2020

Сообщений: 3

25.01.2020, 15:56

 [ТС]

3

как говорится, пока сам не начнёшь разбираться…
в общем если вам пишет invalid syntax, то проверьте PATH. если не помогло, то у вас скорее всего не утановлен сам установщик библиотек pip. ищите в папку scripts там где утанвлен python, в этой папке надите файл pip, установите его и должно всё заработать.



0



Эксперт Python

5403 / 3827 / 1214

Регистрация: 28.10.2013

Сообщений: 9,554

Записей в блоге: 1

25.01.2020, 16:16

4

Цитата
Сообщение от BobyBorn
Посмотреть сообщение

в общем если вам пишет invalid syntax, то проверьте PATH

Неверно. SyntaxError: invalid syntax это ошибка интерпретатора. К PATH никакого отношения не имеет.
Ваша ошибка — вы вводите команду не там, где нужно.

Добавлено через 1 минуту

Цитата
Сообщение от BobyBorn
Посмотреть сообщение

ищите в папку scripts там где установлен python, в этой папке найдите файл pip, установите его и должно всё заработать.

Если pip там есть, то ничего устанавливать уже не нужно.



2



0 / 0 / 0

Регистрация: 25.01.2020

Сообщений: 3

26.01.2020, 12:30

 [ТС]

5

ну как так, «ты пишешь не в cmd» а комбинация вин+R и последующее написание в открывшимся окне «cmd» и нажатие enter что открывает? «если pip там есть, то ничего устанавливать не нужно» — как же мне тогда это помогло? то есть пока я не открыл файл pip, у меня на команду pip install «какая то библиотека» был ответ invalid syntax, то после у меня заработала команда pip и я смог устанавливать интересующие меня библиотеки. чудеса… но я, все равно, все не правильно делаю и пишу не cmd)))

Миниатюры

НЕ работает PIP
 



0



Эксперт Python

5403 / 3827 / 1214

Регистрация: 28.10.2013

Сообщений: 9,554

Записей в блоге: 1

26.01.2020, 16:09

6

Как же тяжело учить нубов….
После того как ты открыл cmd, ты должен ввести команду pip install модуль сразу же. А не после того, как написал команду python. Потому что команда python запускает интерактивный режим интерпретатора Python. И теперь все что ты пишешь — уже относится не к cmd, а Python коду.
В этом была твоя начальная ошибка.
>>>
это приглашение интерепратора Python, а не cmd. Отсюда и ошибка invalid syntax, которая никакого отношения в PATH и cmd не имеет. Учи матчасть.

Ну а далее — методом тыка ты нашел файл pip, открыл cmd в каталоге Scripts и ввел команду. Это — правильно. Но описал все это ты неправильно, чем вводишь в заблуждение других.

P.S. Python нужно было сразу ставить с добавлением его в PATH (для этого есть специальная галочка при установке). Тогда нет необходимости переходить в каталог Scripts для запуска pip.



3



1 / 1 / 0

Регистрация: 20.11.2020

Сообщений: 1

20.11.2020, 05:50

7


Спасибо большое от нуба!



1



0 / 0 / 0

Регистрация: 09.07.2021

Сообщений: 19

20.12.2021, 14:48

8

А что мне делать, если я открываю cmd и пишу строку- pip install pytelegrambotapi.
«pip» не является внутренней или внешней командой, исполняемой программой или пакетным файлом.- это пишет cmd.
ХЕЕЕЕЕЛПППП, помогите



0



Автоматизируй это!

Эксперт Python

6375 / 4122 / 1133

Регистрация: 30.03.2015

Сообщений: 12,194

Записей в блоге: 29

20.12.2021, 15:02

9

Haker_228, значит ты не хакер и как то криво установил питон (пип ставится вместе с ним)



0



0 / 0 / 0

Регистрация: 09.07.2021

Сообщений: 19

20.12.2021, 15:05

10

Welemir1, спасибо за комментарий, но лучше бы помог, а не сидел и умничал.



0



Автоматизируй это!

Эксперт Python

6375 / 4122 / 1133

Регистрация: 30.03.2015

Сообщений: 12,194

Записей в блоге: 29

20.12.2021, 15:11

11

Haker_228, я тебе и помог — установи питон, только вдумчиво. Может вот это поможет

Не по теме:

Цитата
Сообщение от Haker_228
Посмотреть сообщение

сидел и умничал.

ну ты же не сдержался, пока ник придумывал и я вот не устоял тоже. 1-1.



0



0 / 0 / 0

Регистрация: 09.07.2021

Сообщений: 19

20.12.2021, 15:15

12

Спасибо, но я так назвал себя в честь ника нашего учителя по информатике на сайте знакомств у него был такой ник.



0



533 / 438 / 47

Регистрация: 17.07.2013

Сообщений: 2,236

21.12.2021, 10:01

13

Цитата
Сообщение от Haker_228
Посмотреть сообщение

ХЕЕЕЕЕЛПППП, помогите

Иногда вместо pip помогает conda, только ей пользоваться надо осторожно



0



IT_Exp

Эксперт

87844 / 49110 / 22898

Регистрация: 17.06.2006

Сообщений: 92,604

21.12.2021, 10:01

Помогаю со студенческими работами здесь

Не работает pip
Собственно, есть задание поставить uWSGI и nginx. При попытке установки вылезает вот что(см…

Pip install Из директории Не работает
Подскажите что не так.
Скачал дистрибутив selenium распаковал его и пытаюсь запустить в проект….

Проблемы с PIP
Пытался установить библиотеку Scikit-learn, с установкой прошло гладко, все загрузилось без…

AdSense, PIP
Ура! 😀

З.Ы. Кто не знает: PIP — &quot;Payment in progress&quot;, &quot;платеж в процессе&quot;.

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:

13

0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии

А вот еще интересные материалы:

  • Яшка сломя голову остановился исправьте ошибки
  • Ясность цели позволяет целеустремленно добиваться намеченного исправьте ошибки
  • Ясность цели позволяет целеустремленно добиваться намеченного где ошибка
  • Pip install discord ошибка
  • Pip install colorama ошибка