libgphoto2 的 Python 接口
项目描述
python-gphoto2 是libgphoto2的综合 Python 接口(或绑定) 。它是使用SWIG构建的,可自动生成接口代码。这提供了对几乎所有 libgphoto2函数的直接访问,但有时以一种相当非 Pythonic 的方式。
其他与 libgphoto2 的 Python 绑定可用: piggyphoto使用ctypes(包含在标准 Python 安装中)与库接口。gphoto2 源代码树包括一些也使用ctypes的Python 绑定。 gphoto2-cffi使用cffi。
<nav class="contents" id="contents" role="doc-toc">内容
</nav>安装(二元轮)
由于 python-gphoto2 版本 2.3.1 为许多 Linux 和 MacOS 计算机提供了“二进制轮子”。其中包括最新版本的libgphoto2库和预构建的 Python 接口模块,这使得安装变得快速和容易。使用pip的--only-binary选项安装以下轮子之一:
sudo pip3 install gphoto2 --only-binary :all:
如果失败,很可能是因为没有可用的轮子与您的计算机兼容。在这种情况下,您必须在安装 python-gphoto2 之前安装下面列出的依赖项。安装过程会编译绑定并将绑定与安装在您计算机上的libgphoto2链接。
树莓派
Raspberry Pi 的二进制轮可从piwheels 获得。您仍然需要安装一些系统包才能使用它们:
sudo apt install libexif12 libgphoto2-6 libgphoto2-port12 libltdl7 sudo pip3 install gphoto2
依赖项
Python:http ://python.org/ 3.5 或更高版本
libgphoto2:http ://www.gphoto.org/proj/libgphoto2/ 2.5.0 或更高版本
构建工具:pkg-config、C 编译器和链接器
在大多数情况下,您应该使用操作系统的包管理器来安装这些。请注意,您需要libgphoto2和 Python 的“开发头文件”。在某些系统上,它们包含在基本包中,但在其他系统上,它们需要单独安装。寻找libgphoto2-dev或libgphoto2-devel或类似的东西。使用命令pkg-config --cflags --libs libgphoto2 python3测试您的安装。
安装(来源)
有几种方法可以安装 python-gphoto2,对安装过程有不同程度的控制。到目前为止,最简单的方法是使用操作系统的包管理器,如果你有幸使用了一个有 python-gphoto2 可用的系统。请注意,这可能不会安装最新版本。
否则,您可以使用pip或通过下载存档或从GitHub获取源来安装它。确保首先安装依赖项。
使用pip安装
最简单的安装方法是使用pip命令。请注意使用--no-binary来防止从二进制轮进行安装:
sudo pip3 install -v gphoto2 --no-binary :all:
由于软件包的模块是在安装过程中编译的,因此此安装可能需要比您预期的更长的时间。-v选项增加了pip的详细程度,因此您可以看到它正在做某事。
安装下载的存档
访问PyPI并下载其中一个 zip 或 tar.gz 文件,然后将其解压缩并切换到新目录。例如:
tar xf gphoto2-2.3.0.tar.gz cd gphoto2-2.3.0
Python 的setuptools用于构建和安装 python-gphoto2:
pip3 wheel . -v sudo pip3 install gphoto2-*.whl
从GitHub安装(需要SWIG)
SWIG ( http://swig.org/ ) 应该可以通过操作系统的包管理器安装。请注意,这可能是 SWIG 的旧版本,而不是用于在PyPI上生成文件的版本。
要安装当前的开发版本,请使用git “克隆” GitHub存储库,然后切换到新目录:
git clone https://github.com/jim-easterbrook/python-gphoto2.git cd python-gphoto2
和以前一样,Python 的setuptools用于构建和安装 python-gphoto2,但现在您必须先运行SWIG才能生成要编译的文件。开发者目录包含一个运行 SWIG 的脚本:
python3 developer/build_swig.py system pip3 wheel . -v sudo pip3 install gphoto2-*.whl
有关更多详细信息,请参阅下面的“运行 SWIG ”。
测试
从 2.3.1 版开始,您可以通过使用python3 -m gphoto2命令运行它来测试您的 python-gphoto2 安装:
python3 -m gphoto2 python-gphoto2 version: 2.3.1 libgphoto2 version: ['2.5.27', 'standard camlibs (SKIPPING docupen)', 'gcc', 'ltdl', 'EXIF'] libgphoto2_port version: ['0.12.0', 'iolibs: disk ptpip serial usb1 usbdiskdirect usbscsi vusb', 'gcc', 'ltdl', 'EXIF', 'USB', 'serial without locking'] python-gphoto2 examples: /usr/lib64/python3.6/site-packages/gphoto2/examples
这显示了 python-gphoto2 和 libgphoto2 版本号,以及示例程序的安装位置。将数码相机连接到您的计算机,打开它,然后尝试以下示例程序之一:
python3 /usr/lib64/python3.6/site-packages/gphoto2/examples/camera-summary.py
如果这可行,那么您就可以开始使用 python-gphoto2 了。
重新安装
如果您更新或移动libgphoto2的安装,Python gphoto2 包可能无法导入 libgphoto2 共享对象文件之一。如果发生这种情况,您需要重建并重新安装 Python gphoto2 包:
sudo pip3 install -v -U --force-reinstall gphoto2
如果您使用pip安装,或者
rm -rf build pip3 wheel . -v sudo pip3 install --force-reinstall gphoto2-*.whl
如果您从源代码安装。
使用 python-gphoto2
libgphoto2的 Python 接口应该允许你做任何你可以在 C 程序中做的事情。但是,仍然缺少一些位和无法从 Python 调用的函数。如果您遇到任何问题,请告诉我。
以下段落显示了 Python 接口与 C 的不同之处。有关 Python gphoto2 API 的典型用法,请参阅示例程序。
“C”接口
这些函数与它们的libgphoto2等效函数尽可能相似。它们中的大多数返回一个您必须检查的错误代码。
使用SWIG自动生成 Python 接口意味着libgphoto2中的每个函数都 应该对 Python 可用。您可以使用pydoc命令(或python -m pydoc,如果您在虚拟环境中使用 pip 安装 gphoto2)显示函数的文档:
jim@firefly ~$ pydoc3 gphoto2.gp_camera_folder_list_files Help on built-in function gp_camera_folder_list_files in gphoto2: gphoto2.gp_camera_folder_list_files = gp_camera_folder_list_files(...) gp_camera_folder_list_files(camera, folder, context) -> int Parameters ---------- camera: gphoto2.Camera folder: str context: gphoto2.Context (default=None) Lists the files in supplied `folder`. Parameters ---------- * `camera` : a Camera * `folder` : a folder * `list` : a CameraList * `context` : a GPContext Returns ------- a gphoto2 error code See also gphoto2.Camera.folder_list_files jim@firefly ~$
本文的第一部分是 SWIG 生成的函数签名和参数列表。(请注意,上下文是可选的——仅当您需要可与上下文关联的回调函数时才需要它。)其余文本复制自 C 源代码中的“doxygen”格式文档。(在线API 文档显示了它的外观。)请注意,这包括一个不在函数签名中的列表参数。在 C 中,这是一个“输出”参数,这个概念在 Python 中并不真正存在。gp_camera_folder_list_files的 Python 版本返回一个包含整数错误代码和列表值的序列。
大多数在 C API 中使用指针参数返回值的libgphoto2函数在 Python API 中都进行了这样的调整。(不幸的是,我没有找到一种方法来说服SWIG在文档中包含这个额外的返回值。您应该使用pydoc来检查 Python 函数预期的实际参数。)
例如,C 代码:
#include "gphoto2.h"
int error;
Camera *camera;
error = gp_camera_new(&camera);
...
error = gp_camera_unref(camera);
有这个 Python 等价物:
import gphoto2 as gp
error, camera = gp.gp_camera_new()
...
请注意,不需要 gp_camera_unref() 调用。删除 Python 相机对象时会自动调用它。
这是一个完整的示例程序(没有任何错误检查):
import gphoto2 as gp
error, camera = gp.gp_camera_new()
error = gp.gp_camera_init(camera)
error, text = gp.gp_camera_get_summary(camera)
print('Summary')
print('=======')
print(text.text)
error = gp.gp_camera_exit(camera)
“面向对象”界面
这是从 Python使用libgphoto2的首选方式。大多数libgphoto2函数已添加为相应 GPhoto2 对象的方法。这允许 GPhoto2 以更“Pythonic”的风格使用。例如,gp.gp_camera_init(camera)可以替换为camera.init()。这些方法还包括错误检查。如果发生错误,它们会引发 Python GPhoto2Error异常。
示例程序可以重写如下:
import gphoto2 as gp
camera = gp.Camera()
camera.init()
text = camera.get_summary()
print('Summary')
print('=======')
print(str(text))
camera.exit()
不需要额外的错误检查。
错误检查
大多数libgphoto2函数返回一个整数来指示成功或失败。Python 接口包含一个check_result()函数来检查这些值并在发生错误时引发GPhoto2Error异常。
此函数还从列表中删除错误代码,例如示例中gp_camera_new()返回的错误代码。使用这个函数,前面的例子变成:
import gphoto2 as gp
camera = gp.check_result(gp.gp_camera_new())
gp.check_result(gp.gp_camera_init(camera))
text = gp.check_result(gp.gp_camera_get_summary(camera))
print('Summary')
print('=======')
print(text.text)
gp.check_result(gp.gp_camera_exit(camera))
在某些情况下,您不希望在发生某些错误时引发异常。您可以通过调整error_severity变量来“微调” check_result()函数的行为:
import gphoto2 as gp
gp.error_severity[gp.GP_ERROR] = logging.WARNING
...
在这种情况下,将记录一条警告消息(使用 Python 的标准日志记录模块),但发生GP_ERROR错误时不会引发异常。然而,这是一种“一揽子”方法,它对所有GP_ERROR错误都一视同仁。最好在特定操作之后测试特定错误条件,如下所述。
GPhoto2Error异常对象有两个可能在异常处理程序中有用的属性 。GPhoto2Error.code存储库函数生成的整数错误,GPhoto2Error.string存储相应的错误消息。
例如,要等待用户连接相机,您可以执行以下操作:
import gphoto2 as gp
...
print('Please connect and switch on your camera')
while True:
try:
camera.init()
except gp.GPhoto2Error as ex:
if ex.code == gp.GP_ERROR_MODEL_NOT_FOUND:
# no camera, try again in 2 seconds
time.sleep(2)
continue
# some other error we can't handle here
raise
# operation completed successfully so exit loop
break
# continue with rest of program
...
当像这样调用单个函数时,直接测试错误值可能比使用 Python 异常更容易:
import gphoto2 as gp
...
print('Please connect and switch on your camera')
while True:
error = gp.gp_camera_init(camera)
if error >= gp.GP_OK:
# operation completed successfully so exit loop
break
if error != gp.GP_ERROR_MODEL_NOT_FOUND:
# some other error we can't handle here
raise gp.GPhoto2Error(error)
# no camera, try again in 2 seconds
time.sleep(2)
# continue with rest of program
...
日志记录
libgphoto2库包含从其各种函数输出消息的函数(例如gp_log() )。这些消息主要用于调试目的,在Python 中使用libgphoto2时查看它们会很有帮助。Python 接口包含一个use_python_logging()函数,用于将libgphoto2日志记录连接到标准 Python 日志记录系统。如果您想查看消息,您应该在程序开始附近调用use_python_logging(),如示例中所示。在正常使用中,您可能不希望看到这些消息(libgphoto2相当冗长),因此这可以通过应用程序中的“详细”或“调试”选项来控制。
libgphoto2日志消息有四个可能的严重级别,每个级别都映射到合适的 Python 日志严重级别。您可以通过将您自己的映射传递给use_python_logging()来覆盖此映射:
import logging
import gphoto2 as gp
...
callback_obj = gp.check_result(gp.use_python_logging(mapping={
gp.GP_LOG_ERROR : logging.INFO,
gp.GP_LOG_DEBUG : logging.DEBUG,
gp.GP_LOG_VERBOSE : logging.DEBUG - 3,
gp.GP_LOG_DATA : logging.DEBUG - 6}))
...
如果您更喜欢使用自己的日志记录系统,您可以在 Python 中定义日志记录回调函数。该函数必须采用 3 或 4 个参数:level、domain、string和一个可选的data。data参数允许您将一些用户数据传递给您的回调函数(例如记录哪个线程发生错误): 回调函数与gp_log_add_func一起安装:
import gphoto2 as gp
...
def callback(level, domain, string, data=None):
print('Callback: level =', level, ', domain =', domain, ', string =', string, 'data =', data)
...
callback_obj1 = gp.check_result(gp.gp_log_add_func(gp.GP_LOG_VERBOSE, callback))
callback_obj2 = gp.check_result(gp.gp_log_add_func(gp.GP_LOG_VERBOSE, callback, 123))
...
如果你有问题怎么办
如果您在 Python gphoto2 接口中发现问题(例如,段错误、缺少函数或没有可用返回值的函数),请在 GitHub“问题”页面(https://github.com/jim- easterbrook/python-gphoto2/issues)或发送电子邮件至jim @ jim-easterbrook 。我。英国_
如果您的问题更普遍,例如难以捕捉多张图像,请尝试使用gphoto2 命令行程序执行您想要执行的操作。如果问题仍然存在,那么可能值得在gphoto-user 邮件列表中询问。邮件列表的另一位读者可能拥有相同的相机型号并且已经知道该怎么做。
一些gphoto2函数的注意事项
gp_log_add_func / use_python_logging
从 python-gphoto2 版本 2.0.0 开始,这些函数返回一个包含错误代码的序列和一个存储回调详细信息的对象。删除此对象时,回调会自动卸载。
在早期版本的 python-gphoto2 中,这些函数返回一个整数 id,必须将其传递给gp_log_remove_func以卸载回调。
gp_context_set_idle_func / gp_context_set_progress_funcs / 等等。
这些函数仅在 python-gphoto2 版本 1.9.0 之后可用。它们返回一个 Python 对象,您的程序必须存储该对象,直到不再需要回调。删除返回的对象会取消回调,因此无需自己执行此操作。请参阅context_with_callbacks.py示例以了解执行此操作的便捷方法。
gp_file_get_data_and_size / CameraFile.get_data_and_size
从 python-gphoto2 版本 1.2.0 开始,这些函数返回一个支持缓冲区协议的FileData对象。通过使用memoryview对象,Python 可以访问数据。这允许在不复制的情况下使用数据。有关典型用法,请参阅copy-data.py示例。
在早期版本的 python-gphoto2 中,这些函数返回一个字节对象,其中包含CameraFile对象中的数据副本。
gp_file_set_data_and_size / CameraFile.set_data_and_size
从 python-gphoto2 2.1.0 版开始,这些函数接受任何类似字节的 object。在早期版本的 python-gphoto2 中,这些函数需要一个字符串及其长度,并且无论如何都不能正常工作。
gp_file_append / CameraFile.append
从 python-gphoto2 2.1.0 版开始,这些函数接受任何类似字节的 object。在早期版本的 python-gphoto2 中,这些函数需要一个字符串及其长度。
gp_camera_file_read / Camera.file_read
buf参数可以是任何公开可写缓冲区接口的 Python 对象。这允许您将文件直接读入 Python 对象,而无需额外复制。请参阅使用memoryview公开bytearray的copy-chunks.py示例。
gp_camera_wait_for_event / Camera.wait_for_event
这些函数返回事件类型和事件数据。您获得的数据取决于类型。 GP_EVENT_FILE_ADDED和GP_EVENT_FOLDER_ADDED事件返回CameraFilePath,其他事件返回None或文本字符串。
运行SWIG
SWIG用于将src/gphoto2中的.i接口定义文件转换为.py和.c文件。然后编译这些以构建到libgphoto2的 Python 接口。从PyPI下载的文件包括SWIG生成的文件,但您可能希望通过再次运行SWIG重新生成它们(例如,测试SWIG或libgphoto2的新版本)。如果你从GitHub下载了 python-gphoto2 源而不是使用PyPI ,你还需要运行SWIG。
开发者目录包含一个运行SWIG的脚本。它需要一个参数:要 swigged 的版本。这可以是系统或数字三元组,例如2.5.27:
python3 developer/build_swig.py system
这将为您计算机上安装的libgphoto2版本构建界面。接口文件创建在名称如src/swig-gp2.5.18 的目录中。此命名方案允许不同版本的libgphoto2。构建接口时选择最合适的版本。
要为libgphoto2的多个版本(例如 v2.5.10 和 v2.5.0)构建接口,您需要将这些版本的源文件放在您的工作目录中,然后再次运行python developer/build_swig.py,指定版本:
python3 developer/build_swig.py 2.5.10
更多信息在文件developer/README.txt中。
执照
本程序是免费软件:您可以根据自由软件基金会发布的 GNU 通用公共许可证条款重新分发和/或修改它,许可证的第 3 版或(由您选择)任何更高版本。
分发此程序的目的是希望它有用,但不提供任何保证;甚至没有对适销性或特定用途适用性的默示保证。有关详细信息,请参阅 GNU 通用公共许可证。
您应该已经收到了一份 GNU 通用公共许可证的副本以及该程序。如果没有,请参阅http://www.gnu.org/licenses/。