自称フルスタックエンジニアのぶろぐ。

pythonやreactや、gcpやawsなどなどについて書いていこうかと思います。

redux-formでハマった話。

登録済みのデータをredux-formで編集する機能を作った時にハマった話。

プルダウン、テキストエリア、チェックボックスチェックボックスに連動したプルダウン
(チェックボックスがONの時に表示されるプルダウン)

を入力項目として持つ画面に、変更機能を実装していた。



テキストエリアは、apiから取得したデータを初期値にセットできたが、 プルダウンが一向にでてこない。

色々調べまくったら、6系の時にそんなバグもあったような記事にたどり着く。

でも使ってるのは7.2


プルダウンだけのアクションを作ってやらないと、復元できないのか・・・・っと違和感たっぷりで アクションを追加しようとした。


最初のプルダウンで問題が発覚していた、チェックボックス連動のプルダウンを確認していなかった。


ダメ元でチェックボックスが付いた状態になるデータで確認してみると・・・




ちゃんとチェックボックスもプルダウンの状態も復元できていた!


差分を確認しても、共通パーツ化しているので差分はなし!

APIの結果をみると・・・・


xxx:1 は復元できない

xxx:'1'は復元できる


これってバグじゃないのか・・・・・

Big Query 入門

Big Queryについて

基本用語

  • プロジェクト
    課金をコントロールし、グローバルな名前空間のルート (BigQuery内のすべてのオブジェクトの名前は、プロジェクトに対する相対的な名前になる)
  • データセット
    共有可能なテーブルの倫理的な集合をさす言葉。 データセットはプロジェクトに所有される。
  • テーブル
    リレーショナルデータベースと同様に、データの行の集合のこと
  • スキーマ
    テーブル内に、スキーマ情報を持つ。

  • ジョブ
    BigQueryが行う非同期な操作は、ジョブによって実行される。

プロジェクト(課金、トップレベルのコンテナ)
データセット(組織、アクセス制御)
テーブル(スキーマを持つデータ)
ジョブ(クエリ、インポート、エクスポート、コピー)

RESTコレクション

  • Projects
    BigQueryが有効になっている一覧を取れる(だけ)
Projects.list()
  • Datasets
    Datasetsはテーブルのコンテナ。 Datasetsコレクションは、
    insert()get()list()update()patch()delete() のRESTfulなメソッドが用意されています。
  • Tables
    Tablesコレクションには、テーブルに関するメタデータが含まれます。
    また、テーブルのデータには、アクセスすることはできません。 Tablesもinsert()get()list()update()patch()delete()のRESTfulなメソッドが用意されています。
  • TableData
    TableDataコレクションは、テーブルのデータにアクセスするためのものです。 TableDataは、list()insertAll()が用意されています。 insertAllは、複数の行をテーブルに挿入するためのRPCメソッドです。
  • Jobs
    Jobsコレクションは、データの追加やクエリなど、BigQueryの「操作」を行うためのものです。 insert()get()list()query()getQueryResults()が用意されています。

分割テーブル

  • 日別でパーティションを自動的にやってくれる。
  • 日付を特定できるカラムが必要。
  • 既存のテーブルを分割テーブルに変更はできない。
  • パーティションの自動削除(有効期限)を指定できる。
既存のデータを移行したい場合は、下記のようなクエリで移行しかない?

bq query --destination_table <project id>:<dataset>.<new table> --time_partitioning_field created_at --use_legacy_sql=false 'SELECT * FROM `<project id>:<dataset>.<old table>`'

ハマりどころ

gcloud config set project <PROJECT_ID>

で、big queryを使いたいプロジェクトを指定しておかないと、baコマンドがdefaultのプロジェクトに実行される。

janomeとmecabについて

janomemecab

pythonで作られたjanomeで、形態素解析を行って見た。

mecab同等の機能だと書かれていたが・・・・

janome

エントリーシート
エントリー 名詞,サ変接続,*,*,*,*,エントリー,エントリー,エントリー
シート   名詞,一般,*,*,*,*,シート,シート,シート

mecab

エントリーシート
エントリーシート        名詞,組織名,*,*,*,*,*
EOS

全然ちがーう。。。

皆さんもお気をつけください。

Google App Engine(GAE) のdeployの話 Part3 ~デプロイに失敗しまくる話~

Google App Engine(GAE) のデプロイに失敗しまくる話

GAEで開発を進めていると、あるタイミングから急にデプロイに時間がかかりだし、ERRORでデプロイできない事業が繰り返される場合がある。

そんな時の対策を記載してみる。

  • cronを止めてdeploy

  • メモリの使用率をグラフで確認し、メモリをチューニング

  • CPUの数を増やす

  • resourcesの記述を消す

  • wokersのcpu * 2 + 1の指定をしている場合、少し減らすように変更する

傾向的に、pandasやjanomeなど、インストールに時間とCPUとメモリを消耗しそうなものを入れるときは、GCEより かなり大きめのスペックが必要だなっという感じ。

数日前に、resourcesを消すとdeployできることが発覚。ただし費用面がまだ見えてない(2018/3/1 追記)

resourcesを決して実行すると(おそらく)最小構成でデプロイされます。

デプロイ失敗がつづいていたのは、一時的なものだったのかも?GCPUG slackでも同じ現象に陥ってる人がいたようですが、今はデプロイスムーズにできてます。(2018/3/20 追記)

あとは、コンテナイメージを作るとデプロイが早くなるらしいので、試してみるのもありかもです。

バッチ処理とかGCEで切り分けられるなら、分けちゃった方がコスト的にも良いかもしれない。

googleさん GAEのデプロイ失敗時に、なんで失敗してるのかを表示してほしい・・・・ (どこかのログでわかるのかな・・・?)

murabo.hatenablog.com

murabo.hatenablog.com

Google App Engine(GAE) のdeployの話 Part2 ~cron編~

Google App Engine(GAE) のcronの話

GAEでバッチ処理を行いたい場合は、バッチ処理の代わりにURLを叩いて処理します。

cron用のエンドポイントが必要になるってことですね。

そのエンドポイントをスケジュール登録して、叩いてもらう流れになります。

下記のように、cron.yamlを作成してdeployすることで、スケジュール設定することが可能です。

cron:
- description: "バッチ1"
  url: /cron/sample_batch1/
  schedule: every 15 minutes from 3:00 to 00:00
  timezone: Asia/Tokyo

- description: "バッチ2"
  url: /cron/sample_batch2/
  schedule: every monday 01:00
  timezone: Asia/Tokyo
  target: sample-api

- description: "バッチ3"
  url: /cron/sample_batch3/
  schedule: every day 08:30
  timezone: Asia/Tokyo
  target: sample-api

- description: "バッチ4"
  url: /cron/sample_batch4/
  schedule: every 1 hours
  timezone: Asia/Tokyo
  target: sample-api

ハマりポイント

App Engine 環境の選択  |  App Engine Documentation  |  Google Cloud

ですが、cronを実行してもworker timeoutと30秒ほどで異常終了となります。

回避策として、

app.yaml

entrypoint: gunicorn --timeout 3600 -b :$PORT sample.wsgi

timeoutの指定が必要です。

・・・これかなりハマりました。。。

やりたかったけど、実現できなかったこと。

毎週月、火、水、木、金の、1時間毎で、08~20時まで

が、いろんなパターン試したが、deploy失敗・・・

結構需要あると思うんだけどなぁ・・・?

murabo.hatenablog.com

python djangoで画像をmodelのImageFieldに保存する時の話。

画像を保存する場合のお話。

  • これに困った経緯 画像の保存先をgoogle cloud storageに保存したい。
    これってどこでどうすれば保存できるんだ・・・から始まった。

静的保存場所の設定

  • settingsにgoogle cloud storageの設定を追加
STATIC_URL = 'https://storage.googleapis.com/[プロジェクト名].appspot.com/static/'
DEFAULT_FILE_STORAGE = 'storages.backends.gcloud.GoogleCloudStorage'
GS_BUCKET_NAME = '[プロジェクト名].appspot.com'
PROJECT_ID = '[プロジェクト名]'

を追加

  • モデルにimageの定義
class Image(models.Model):
    img = models.ImageField(null=True, blank=True, upload_to='img')
  • views
    今回はrest apiだったので、restのview
    base64で画像を受け取る想定
import base64, request
from django.core.files.base import ContentFile

class ImageViewSet(ModelViewSet):
    queryset = Image.objects.all()
    serializer_class = ImageSerializer

    def create(self, request, *args, **kwargs):
        data = request.data.get('img')
        if data:
            format, imgstr = data.split(';base64,')
            ext = format.split('/')[-1]
            request.data['img'] = ContentFile(base64.b64decode(imgstr), name='temp.' + ext)
        return super(ImageViewSet, self).create(request)

URLから取得した画像を保存したい時

import request
from .models import Image
from django.core.files.base import ContentFile

url = 'http://xxxxxxxxx/abc.jp'
file_name = 'img/{}'.format(urlparse(url).path.split('/')[-1]) 
response = requests.get(url)
image = Image()
image.img.save(file_name, ContentFile(response.content, file_name), save=True)

murabo.hatenablog.com

murabo.hatenablog.com

Google App Engine(GAE) のdeployの話 Part1

Google App Engine(GAE) のdeployの話

GAE とは

Google App Engine (GAE) は、Googleの提供するサービスの1つであり、
ウェブアプリケーションをPHP・Python・Java・Go言語を使用して開発し、
Googleのインフラストラクチャー上で実行し、バージョン管理することができる。
Google Cloud Platformの一部。

※上記wiki抜粋

簡単に言うと、

開発したやつを簡単にデプロイできて、運用管理も楽チンだよ。 バージョン管理もできるし、異なるバージョンを同時に稼働させてABテストなんかもできちゃうんだよ

っという代物です。

GAE standard と flexible

GAEには、standardとflexibleがあります。

違いについてはオフィシャルを参考にしていただいた方が良いかと思います。

僕のpythonで経験した情報と所感を書いて見ます。

standard

pythonは2しか使用できません。 pip install を自分のプロジェクト内に展開しておいて、そのプロジェクト毎deploy(upload)する感じでした。 特に問題なさそうな話ですが、GAE内ですでに入っているパッケージなんかもあり、GAE環境に依存したパッケージの管理が必要になります。 レアケースかもしれませんが、deployしても、ソースの状態が反映されない(バージョンの向き先は最新になっているのに)問題が頻発しました。

flexible

pythonは2も3も指定できます。 pip モジュールは、requirements.txtに記載されているものをインストールしてくれます。 従来の構造のままdeployできる感じで、こちらの方がしっくりきました。 ソースが反映されないような問題にも直面せず、問題なさそうです。

ここからは先は、flexibleを採用したのでflexibleについての記載となります。

GAEのdeploy方法

app.yamlの記入例

runtime: python
env: flex
entrypoint: gunicorn -b :$PORT core.wsgi

# ここの名前を変更する事で、同一のプロジェクト内に、複数のサービスとしてdeployできます。
service: sample-api

runtime_config:
  python_version: 3


beta_settings:
    cloud_sql_instances: [プロジェクト名]:asia-northeast1:[db名]

manual_scaling:
  instances: 2
resources:
  cpu: 2
  memory_gb: 1.4
  disk_size_gb: 10
  • deploy コマンド

gcloudコマンドは、こちらからインストールする必要があります。

gcloud app deploy app.yaml --project [プロジェクト名]

上記コマンドを実行すると、時間はかかりますが簡単にdeploy完了です。




次回は、GAEでバッチ処理なんかについて記載しようと思います。

murabo.hatenablog.com

murabo.hatenablog.com