【Python】Geohashを求めるお話

Geohash値を求めたいとき、ありますよね。

PythonでGeohashを使いたいときに使用したモジュールがこちら

pypi.org

他にもシンプルに「Geohash」というモジュールもありました

Geohash · PyPI

最初こちらの"Geohash"モジュールを使おうとしたところ、pipでインストールして
「import geohash」としてもModule Not Found的なことが出てくる。


調べると、なんか解決策はありそうですがインストールしたgeohashモジュールのファイル移動やらなんやらを
しなくちゃいけないらしく、Python初心者の私はわからず。


ということで、Python-geohashモジュールを使うことにしました。

pip3 install python-geohash

インストールします。次にimportしますがpython-geohashなら先程のエラーは出ません。

>>> import geohash

>>> print(geohash.encode(35.6809591, 139.7673068))
xn76urx2wkce

>>> print(geohash.encode(35.6809591, 139.7673068, 4))
xn76

試しに東京駅の緯度経度 35.6809591 ,139.7673068 でGeohashを求めてみました。
いい感じです。

第3引数に桁数入れるとその桁数のGeohashになります。

範囲の広いGeohashってことになるのかな。

Lambdaで外部モジュールを使う方法

Lambdaで外部モジュールを使うにはLayerを使用する。
コンソールでいう、Lambdaを押すとその他のリソースってところにあるやつ。


流れとしては、入れたいモジュールをzipで固めて、LambdaのLayerにアップロード。
アップロードしたLayerを、モジュールを使いたいLambdaに紐付ける。(インラインコード編集の下の方にある)


まずはローカル環境(mac)でモジュールをインストール

pip install <モジュール名> -t ./python


pythonって名前のディレクトリに入れなきゃ行けないらしい。
で、zipでpythonディレクトリごと圧縮して、Layerにアップロード。

zip -r python.zip ./python
[ERROR] Runtime.ImportModuleError: Unable to import module 'lambda_function': 

IMPORTANT: PLEASE READ THIS FOR ADVICE ON HOW TO SOLVE THIS ISSUE!

Importing the numpy C-extensions failed. This error can happen for
many reasons, often due to issues with your setup or how NumPy was
installed.

We have compiled some common reasons and troubleshooting tips at:

    https://numpy.org/devdocs/user/troubleshooting-importerror.html

Please note and check the following:

  * The Python version is: Python3.8 from "/var/lang/bin/python3.8"
  * The NumPy version is: "1.20.3"

and make sure that they are the versions you expect.
Please carefully study the documentation linked above for further help.

Original error was: No module named 'numpy.core._multiarray_umath'

Traceback (most recent call last):


エラー出ました。


バージョンがどうのこうの、依存関係がどうのこうの言ってるぽい。
でもバージョンは正しい。

ローカルでモジュールzip作成やったのがいけないっぽい!


LambdaはAmazon Linux(2)で動いているので、


・EC2でAmazon Linux(2)のインスタンスを立てる

もしくは

・Lambdaのdocker imageを利用する
→python3.8の場合
amazon/aws-sam-cli-build-image-python3.8


私はdockerの方でやりました。

$ docker run -it -v $(pwd):/var/task amazon/aws-sam-cli-build-image-python3.8:latest

bash-4.2# pip install <モジュール名> -t ./python
bash-4.2# exit

$ zip -r python.zip ./python

今度はエラー出ずに無事にLayerにアップロード&モジュール使えるようになりました

API Gateway プロキシ統合のLambdaのレスポンス形式について

地味にハマってしまうやつ!

REST APIのプロキシ統合を利用してAPI Gateway,Lambdaを使用した場合
Lambdaからのレスポンスは決まった形式にしないと500エラーが発生します。

プロキシ統合のための Lambda 関数の出力形式docs.aws.amazon.com

「関数出力が別の形式である場合、API Gateway502 Bad Gateway エラーレスポンスを返します。」とはっきり書いてあります。
python,Lambda初心者の私は「return 1」と1を返却しており、これにハマってしまいました。


そもそもプロキシ統合とは?ってところですが

簡単に言えば

レスポンスやリクエストの面倒なマッピングをいい感じにやってくれるやつって感じです。
わざわざマッピングする必要なし。

プロキシ非統合の場合はマッピングしなきゃなんですね。

API GatewayのHTTP APIのbodyがbase64でエンコードされている件

REST APIの方では勝手にエンコードされることなんてなかったので、びっくり。

Lambdaで受け取る際、base64デコードしてやりましょう。

import base64

def lambda_handler(event, context):
 
    data = base64.b64decode(event['body'])  # b'Hello world'

    data.decode('UTF-8')   #Hello world
    #以下略

base64デコードしたデータはbytes型になっているので、これもstr型に直すためデコードする。