以前紹介したMinIOをPythonで操作してみたいと思います。
過去の記事はこちら
MinIOはAmazon S3互換であるためAmazon S3を操作する際のPythonモジュールを使用することで使用することができます。今回はBoto3というPythonモジュールを使用してみたいと思います。
Boto3とは
Boto3はAWSが公式で提供している、Amazon S3をPythonから操作するためのライブラリです。Amazon S3がAPIとして公開している機能をBoto3を使うことで利用することができます。
インストール
Boto3のインストールはpipコマンドから行うことができます。
pip install boto3
実際に使ってみる
Boto3を使ってMinIOを操作してみたいと思います。まずは前回作成したバケットにアップロードされているファイルの一覧を取得してみましょう。
import boto3 s3 = boto3.client("s3", endpoint_url="http://127.0.0.1:9000", aws_access_key_id='minioadmin', aws_secret_access_key='minioadmin') object_list = s3.list_objects(Bucket='test').get("Contents") print(object_list)
実行した結果は下記の通り
[ { 'Key': 'minio_01.png', 'LastModified': datetime.datetime(2020, 7, 23, 16, 39, 18, 470000, tzinfo=tzutc()), 'ETag': '"c1acffd60da35db4c180b0a5858dd735"', 'Size': 18253, 'StorageClass': 'STANDARD', 'Owner': { 'DisplayName': '', 'ID': '02d6176db174dc93cb1b899f7c6078f08654445fe8cf1b6ce98d8855f66bdbf4' } } ]
Keyにはアップロードされているファイル名が入ってきます。 今回はアップロードされている`minio_01.png'を取得したいと思います。 ファイルのダウンロードにはdownload_fileを使用します。
使い方は
download_file('Bucket名', 'バケット上のobject名', '保存先のfilepath')
でファイルをダウンロードすることができます。
import boto3 s3 = boto3.client("s3", endpoint_url="http://127.0.0.1:9000", aws_access_key_id='minioadmin', aws_secret_access_key='minioadmin') file = s3.download_file('test',"minio_01.png", "./minio_01.png")
上記の実行結果としてカレントディレクトリに'minio_01.png'が保存できていることが確認できます。
MinIO用のPythonパッケージ
実はMinIO用のPythonパッケージもあります。私の場合は開発するPythonプログラムの実動作環境がAmazon S3で、ローカルの開発環境でAmazon S3の代わりとしてMinIOを使用するため、Amazon S3互換のboto3を使用することが多いのですが、最初からMinIOしか使用しないのであれば、MinIO用のPythonモジュールを使うといいかもしれません。
minioのインストール
minioはpipコマンドでインストールすることができます。
pip install minio
また、gitリポジトリからダウンロードして使用することもできます。
git clone https://github.com/minio/minio-py
cd minio-py
python setup.py install
実際に使ってみる
先ほどのようにファイルリストを取得して、その後ファイルを取得したいと思います。
from minio import Minio minioClient = Minio('127.0.0.1:9000', access_key='minioadmin', secret_key='minioadmin', secure=True) objects = minioClient.list_objects('test', prefix='', recursive=True) for obj in objects: print(obj.object_name.encode('utf-8'))
しかし、上記の結果がエラーになってしまいます。。。なぜでしょうか・・・
$ python3 list_objects.py Traceback (most recent call last): File "/home/testuser/.local/lib/python3.6/site-packages/urllib3/connectionpool.py", line 672, in urlopen chunked=chunked, File "/home/testuser/.local/lib/python3.6/site-packages/urllib3/connectionpool.py", line 376, in _make_request self._validate_conn(conn) File "/home/testuser/.local/lib/python3.6/site-packages/urllib3/connectionpool.py", line 994, in _validate_conn conn.connect() File "/home/testuser/.local/lib/python3.6/site-packages/urllib3/connection.py", line 394, in connect ssl_context=context, File "/home/testuser/.local/lib/python3.6/site-packages/urllib3/util/ssl_.py", line 370, in ssl_wrap_socket return context.wrap_socket(sock, server_hostname=server_hostname) File "/usr/lib/python3.6/ssl.py", line 407, in wrap_socket _context=self, _session=session) File "/usr/lib/python3.6/ssl.py", line 817, in __init__ self.do_handshake() File "/usr/lib/python3.6/ssl.py", line 1077, in do_handshake self._sslobj.do_handshake() File "/usr/lib/python3.6/ssl.py", line 689, in do_handshake self._sslobj.do_handshake() ssl.SSLError: [SSL: WRONG_VERSION_NUMBER] wrong version number (_ssl.c:852) During handling of the above exception, another exception occurred: Traceback (most recent call last): File "list_objects.py", line 29, in <module> for obj in objects: File "/home/testuser/.local/lib/python3.6/site-packages/minio/api.py", line 1036, in list_objects headers=headers) File "/home/testuser/.local/lib/python3.6/site-packages/minio/api.py", line 1984, in _url_open region = self._get_bucket_region(bucket_name) File "/home/testuser/.local/lib/python3.6/site-packages/minio/api.py", line 1919, in _get_bucket_region region = self._get_bucket_location(bucket_name) File "/home/testuser/.local/lib/python3.6/site-packages/minio/api.py", line 1950, in _get_bucket_location headers=headers) File "/home/testuser/.local/lib/python3.6/site-packages/urllib3/poolmanager.py", line 330, in urlopen response = conn.urlopen(method, u.request_uri, **kw) File "/home/testuser/.local/lib/python3.6/site-packages/urllib3/connectionpool.py", line 760, in urlopen **response_kw File "/home/testuser/.local/lib/python3.6/site-packages/urllib3/connectionpool.py", line 760, in urlopen **response_kw File "/home/testuser/.local/lib/python3.6/site-packages/urllib3/connectionpool.py", line 760, in urlopen **response_kw [Previous line repeated 2 more times] File "/home/testuser/.local/lib/python3.6/site-packages/urllib3/connectionpool.py", line 720, in urlopen method, url, error=e, _pool=self, _stacktrace=sys.exc_info()[2] File "/home/testuser/.local/lib/python3.6/site-packages/urllib3/util/retry.py", line 436, in increment raise MaxRetryError(_pool, url, error or ResponseError(cause)) urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='localhost', port=9000): Max retries exceeded with url: /test?location= (Caused by SSLError(SSLError(1, '[SSL: WRONG_VERSION_NUMBER] wrong version number (_ssl.c:852)'),))
公式が出しているSampleを使ってもうまくいかないですね・・・ list_objects.py - minio/minio.py
とりあえず取得したいファイル名はわかっているので、ファイルが取得できるか試してみたいと思います。
from minio import Minio minioClient = Minio('127.0.0.1:9000', access_key='minioadmin', secret_key='minioadmin', secure=True) file = s3.fget_object('test',"minio_01.png", "./minio_01.png")
うーん・・・上記もうまく動かないですね・・・
例によって公式が出してるSampleでも動かないです・・・ぐぬぬ・・・
fget_object.py - minio/minio-py
まとめ
本来であれば、どっちのモジュールの方が使いやすいかというのをお伝えしたかったのですが、うまく動かずでした。引き続き調べてみたいと思います。 MinioをPythonで使うときはBoto3を使った方がうまく動きそうなのと、Boto3の方が広く使われているモジュールなのでトラブルシューティングがしやすいと感じました。MinioはAmazon S3と互換性がありますし、そのままBoto3を使用するのが良いのかもしれないと思います。