はてなの金次郎

とあるエンジニアの技術系ブログ

はじめてのPyPIを公開しました

はじめに

PyPIデビューをしましたので、登録したライブラリとPyPI登録方法を紹介させていただきます。

aws-sm

github.com

Secrets Managerからデータベースの認証情報やAPIKeyなどのアプリケーションの環境変数を安全に取得することができます。

CircleCIでテスト・文法チェック・コードメトリクス計測のCI構築や、pyupでサードパーティ自動セキュリティアップデートの構築を行いました。

Secrets Managerの説明や利用するシチュエーションなどの詳細は別記事をご覧ください。

qiita.com

インストール

pipで簡単にインストールできます。

$ pip install aws-sm

使い方

SecretsManager クラスをインポートして、シークレット名と取得したい環境変数名を適切に設定することで環境変数を取得できます。

from aws_sm import SecretsManager

AWS_ACCESS_KEY_ID = ***************
AWS_SECRET_ACCESS_KEY = ***************

secretsmanager = SecretsManager('ap-northeast-1', AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY)
secrets = secretsmanager.get_secret_values('tutorials/MyFristTutorialSecret')

USER_NAME = secretsmanager.get_secret_value('USER_NAME', secrets)
PASSWORD = secretsmanager.get_secret_value('PASSWORD', secrets)

PyPI登録方法

Packaging Python Projects — Python Packaging User Guide

公式ドキュメントにPyPIの登録方法がまとまっているのでこの通りに行いましたが、私の環境では一点だけうまくいきませんでした。

それは、TestPyPIやPyPIへのアップロードで利用するtwineコマンドを利用する時です。

$ twine upload dist/*
-bash: twine: command not found

ドキュメント通りにコマンドを叩いたのですが、 twine: command not found と怒られてしまいました。 検索してみると同じような現象に遭遇している方がいらっしゃいました。

$ python3 -m twine upload dist/*

とすることで正常に動作しました。ちなみに、 -m-m mod : run library module as a script (terminates option list) というオプションです。

おわりに

OSSへの貢献は身につく力が大きいなと改めて感じました。はじめてのこととなると失敗も多かったですが、そのトライアンドエラーの工程が自分を大きく成長させてくれたと思います。 PyPIへの登録自体はドキュメントのおかげで比較的簡単にできましたので興味のある方はぜひ試してみてはいかがでしょうか。

コテコテのGitLabユーザがCircleCIに入門してみた

はじめに

GitLabユーザがGitHubでCI構築するためにCircleCIに入門する物語です。

GitLab 10.6でGitLab CI/CD for Githubがリリースされているのにもかかわらず、CircleCIを選定した理由は以下です。

  • GitHub.comで利用されているCIサービス第2位(2017年時点)

blog.github.com

  • ForresterにLeaderという最上位のランクに認定されている

www2.circleci.com

  • 単純にほかのCIサービスを触ってみたかった
  • CircleCI 2.0がいい感じらしい

ちなみに、GitLab CI/CD以外に他のCIサービスを触るのは初めてです。なんだがいけないことをしているような気分です。

まずは、GitLab CI/CD、CircleCIがそれぞれどんなサービスで何を売りとしているのかを理解してみます。

GitLab CI/CDって何?

about.gitlab.com

GitLab has integrated CI/CD pipelines to build, test, deploy, and monitor your code Rated #1 in the Forrester CI Wave™

Forresterに認められたNo.1CIサービス。

https://about.gitlab.com/features/gitlab-ci-cd/

GitLab supports development teams with a well-documented installation and configuration processes, an easy-to-follow UI, and a flexible per-seat pricing model that supports self service. GitLab’s vision is to serve enterprise-scale, integrated software development teams that want to spend more time writing code and less time maintaining their tool chain

Forresterのレポートによると、整備されたドキュメントや使いやすいUI、GitLabのビジョンが賞賛されています。

GitLabへの移行で他のCIサービス使っているというケースは考えられますが、よっぽどの変態でもない限り、GitLabを使っているならGitLab CI/CDを選択するのがおそらく一般的なのではないでしょうか。

CircleCIって何?

circleci.com

Power, Flexibility, and Control CircleCI gives your team more speed and configurability than ever before.

他サービスとの柔軟な連携や容易な設定が売りのようです。 ForresterにはGitLabと同じくLeaderに認定されています。

Organizations striving to be lean and stay lean will appreciate the simplified, nearly zero-maintenance approach CircleCI provides. Existing customers will appreciate the new features of CircleCI 2.0 that appear to completely address all the top asks that customers are looking for.

Forresterのレポートによると、ほぼ保守が不要な点と2.0の新機能が賞賛されています。

GitHubであればTravis CIに続いて2番目のシェア率と利用者も多いようです。

それぞれ何となくどんなサービスなのかはわかりましたが、まだボヤけているのでGitLab CI/CDとCircleCIの違いを調べてみることにしました。

GitLab CI/CD vs CircleCI

なんと、それぞれサービスであのCIサービスとはここが違うという主張がまとまっているページがありました。 それぞれの主張を列挙してみます。

GitLab CI/CDの主張

about.gitlab.com

  • CLI, API, Webhookを提供しており、これらを活用することで他サービスとの連携が可能である。
  • GitLab CI/CD にあってCircleCIにない機能が29個ある。
    • Application performance monitoring and alerts
    • Preview your changes with Review Apps
    • Code Quality
    • Show code coverage rate for your pipelines
    • Auto DevOps
    • Easy integration of existing Kubernetes clusters
    • Easy creation of Kubernetes clusters on GKE
    • etc...

CircleCIの主張

circleci.com

  • チームの成長段階に合った最適なツールとの統合ができる。
    • GitHub, BitBucket, Slack, AWSなど、サービス切り替えが容易である。
    • GitLab CIはGitLabのユーザしか使えない。
  • CI/CDにのみ焦点を当てたサービスである。
  • buildersの管理が容易。
    • GitLab Runnerは独自で管理する必要がある。

CircleCIのGitLabはこうだという主張に誤りがあるように感じますが、まとめると、

GitLab CI/CD「GitLabは、DevOpsを実現するための統合ツールであり、我々はその一つのサービスである。DevOpsを実現するための機能をたくさん提供している。」

CircleCI「私たちは何かのツールに依存したサービスではない。CI/CDにのみ焦点を当てており、他サービスとの連携・切り替えが容易である。」

みたいなイメージかなと思います。

CircleCIを使ってみた

実際のリポジトリはこちらです。

github.com

version: 2
jobs:
  build:
    working_directory: ~/aws-sm
    docker:
      - image: circleci/python:3.7
    steps:
      - checkout
      - run: sudo chown -R circleci:circleci /usr/local/bin
      - run: sudo chown -R circleci:circleci /usr/local/lib/python3.7/site-packages
      - restore_cache:
          key: deps1-{{ .Branch }}-{{ checksum "Pipfile.lock" }}
      - run:
          command: |
            pipenv install --system --dev
      - save_cache:
          key: deps1-{{ .Branch }}-{{ checksum "Pipfile.lock" }}
          paths:
            - ".venv"
            - "/usr/local/bin"
            - "/usr/local/lib/python3.7/site-packages"
      - run:
          command: |
            py.test --tb=line --cov-report=html
      - store_artifacts:
          path: htmlcov/
      - run:
          command: |
            flake8
      - run:
          command: |
            radon cc -n C .
            radon mi -n B .

テスト、文法チェック、コードメトリクス計測を走らせてみました。 以下の config.yml を参考にさせていただきました。

github.com

感想

いい感じ

  • GitHubのアカウントを持っていれば簡単に利用を始められる
  • OSと言語を選択することでYAMLの雛形を生成してくれる
  • GitLab CI/CDに似た構文である(CIサービス自体がそこまで異なる構文になるとは思っていませんでしたが)

なんだかなぁ

  • プルリクを作成するまでCIの実行結果をGitHub上で確認できない(Failした時はメールで通知される)
  • ジョブが失敗していてもマージできてしまう
  • coverageのバッジを生成できない

「なんだかなぁ」に関してはこれを解消するための方法があるかもしれません。入門者が「あれ?」と思った点です。

おわりに

使っている時間が全く違うのでかなりGitLab CI/CDに偏った意見になりますが、統合ツールとしてのGitLabの使いやすさを実感する時間になりました。

GitLabはGitLab上でCI/CDの実行結果の確認ができ、CIが失敗した際にはマージボタンが押せません。また、coverageのバッジを自動生成してくれるような設定が可能です。

しかし、かなりの短時間でテストの自動化が実現できたCircleCIは素晴らしいCIツールだと思います。GitHubではCircleCI使っていきたいです。

今回試したのはテストのみだったのでビルド、デプロイも実装してみるとCircleCIの便利さがより見えてくるかもしれません。 今後機会があれば試してみたいです。

テキストマイニングによるTwitter個人アカウントの性格推定

はじめに

pycon.jp

PyConJP 2018で「テキストマイニングによるTwitter個人アカウントの性格推定」というタイトルでLTをさせていただきました。

普段はサーバーサイドエンジニアとしてスマホアプリのバックエンドサーバー開発を主にPython/Djangoで行っています。

LT参加の動機は、Pythonを使っている身として機械学習に触れてみたかったからです。

Webアプリケーション開発でしかPythonを使ったことがありませんでしたが、Pythonといえばデータサイエンスのイメージがあります。

採択されてもされなくても、PyConJPのLTという機会で普段は知らないPythonの一面を掘り下げてみようと思いました。

スライド

speakerdeck.com

YouTube

Gihyo

PyConJPの公式カンファレンスレポートで紹介していただきました。

正直「ちょっとストーカーの話っぽいけど大丈夫なの?」とスタッフ同士顔を見合わせる場面もあったのですが,終わってみると真面目でユーモアもある発表だったと思います。

gihyo.jp

Twitterの反応

Twitterで嬉しい反応をたくさんいただきました!ありがとうございます!

togetter.com

Twitterアカウントの性格推定

ツイートの収集

まずはツイートの収集です。Twitter社が提供するTwitter APIを利用してツイートを取得します。

クライアントの実装として、すぐにパッと思い付くのは requests を用いた実装です。

github.com

HTTP for Humans とデカデカと主張しているように、直感的にHTTPの通信を実装できます。

これは urllib2 の使いにくさを酷くディスった表現ですが、Python3で urllib.request が標準ライブラリとして提供されている今、 こちらを使うのも一つの選択肢ではないかと思います。

urllib2 と比べ格段に使いやすくなっています。

urllib.request --- URL を開くための拡張可能なライブラリ — Python 3.9.1 ドキュメント

例えば、AWS LambdaをPython3で使う場合は外部ライブラリをimportするためには少々手間がかかるため、 urllib.request を選択するのが良いと思います。

今回のLTでは簡潔に実装できて、GitHubスター数もそこそこあったので python-twitter というライブラリを用いることにしました。

github.com

import twitter

api = twitter.Api(
    consumer_key=CONSUMER_KEY,
    consumer_secret=CONSUMER_SECRET,
    access_token_key=ACCESS_TOKEN_KEY,
    access_token_secret=ACCESS_TOKEN_SECRET
)

tweets = api.GetUserTimeline(screen_name='jumpyoshim', count=2)

collectionsのnamedtupleのようなデータ構造で返却されるため、注意が必要です。

IN

[tweet.text for tweet in tweets]

OUT

['RT @akucchan_world: 吉村さんのLTです。\n#pyconjp https://t.co/ZCvHY9ebcw',
 'PytestのTDD実践ためになった #pyconjp']

文章のベクトル化

続いて、収集したツイートを数値計算しやすいようにベクトル化します。

ベクトル化の手法として、3つほど確認できました。

https://tifana.ai/words/natural-language-processing/9302.htmltifana.ai

deepage.net

deepage.net

Word2VecやDoc2Vecに関しては、まだ咀嚼しきれない部分があったため、今回はBoWを選択しました。

BoWは、単語の頻出度のみを考慮して、単語の頻出度をベクトル化したものが最も近いデータを推定結果としているだけです。

Word2VecやDoc2Vecは単語の並び順なども考慮するらしく、推定精度が上がるらしいです。まだまだ勉強不足、今後の課題です。

形態素解析

ベクトル化するために、まずは形態素解析をする必要があります。

形態素解析のツールとして、3つほど確認できましたが、環境構築が容易で速度もはやいMeCabを選択してみました。

IN

import MeCab

tagger = MeCab.Tagger('mecabrc')
data = []
for tweet in tweets:
    node = tagger.parseToNode(tweet.text)
    words = []
    while node:
        meta = node.feature.split(',')
        if meta[0] == '名詞':
            words.append(node.surface.lower())
        node = node.next
    data.append(words)
print(data)

OUT

[['rt', '@', 'akucchan', '_', 'world', ':', '吉村', 'さん', 'lt', '#', 'pyconjp', 'https', '://', 't', '.', 'co', '/', 'zcvhy', '9', 'ebcw'], ['pytest', 'tdd', '実践', 'ため', '#', 'pyconjp']]

形態素解析の際、実際にはURLや@アカウント名、リツイートなどを正規表現で空文字で置換することで、形態素解析された際に意味をなさない単語を排除します。

MeCabJanomeに関してはpipでインストールできるため利用しやすいですね。

JUMANは環境構築がやや手間ですが、かなり高精度の形態素解析をしてくれるみたいです。

pypi.org

pypi.org

JUMAN - KUROHASHI-CHU-MURAWAKI LAB

特徴ベクトル

形態素解析した単語群は gensim を用いて辞書を作成し、ベクトル化します。

from gensim import corpora, matutils

dictionary = corpora.Dictionary(data)
data_train = []
for datum in data:
    bow = dictionary.doc2bow(datum)
    dense = list(matutils.corpus2dense([bow], num_terms=len(dictionary)).T[0])
    data_train.append(dense)
print(data_train)

OUT

[[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]]

github.com

文書分類器

ここまででデータを揃えることができたので、正解ラベルを用意して学習を行います。

正解ラベルはエゴグラムの診断結果を利用します。Twitter上にエゴグラムの診断結果をツイートするアカウントが多く存在するためです。

以下の23パターンがあります。

  • ネクラ厭世タイプ(W型)
  • 明朗楽観タイプ(M型)
  • 優柔不断タイプ(N型)
  • ハイパワータイプ(逆N型)
  • 頭でっかちタイプ(逆V型)
  • お手あげタイプ(V型)
  • 典型的ネクラタイプ(U型)
  • ぼんぼんタイプ(逆U型)
  • 頑固オヤジタイプ(左上がり型)
  • ガキ丸出しタイプ(右上がり型)
  • ハイレベルタイプ(オールA型)
  • 中庸タイプ(オールB型)
  • 原始人タイプ(オールC型)
  • ルーズタイプ(CP欠乏型)
  • クールタイプ(NP欠乏型)
  • 現実無視タイプ(A欠乏型)
  • 自閉症タイプ(FC欠乏型)
  • 気ままタイプ(AC欠乏型)
  • 口うるさタイプ(CP型)
  • お人好しタイプ(NP型)
  • コンピュータタイプ(A型)
  • 自由奔放タイプ(FC型)
  • 自己卑下タイプ(AC型)

機械学習

scikit-learn を利用することで簡単に機械学習ができます。

IN

from sklearn.ensemble import RandomForestClassifier

clf = RandomForestClassifier()
label_train = ['ネクラ厭世タイプ(W型)', '明朗楽観タイプ(M型)']
clf.fit(data_train, label_train)
clf.predict(data_train)

OUT

array(['ネクラ厭世タイプ(W型)', '明朗楽観タイプ(M型)'], dtype='<U12')

学習させたデータを推定してみると、当然同じタイプが推定されることが確認できます。

github.com

感想

たとえ数学的な知識に疎くても、gensimやscikit-learnといったライブラリを利用すれば簡単に実現できてしまうのがPythonのすごいところだと感じました。

今後は数学的な知識をより深めたり、機械学習をWebアプリケーションに組み込んだりしてみたいです。今後もPythonを使っていろいろなチャレンジをしていきたいです。

おわりに

今回はPyConJPということでPythongensimscilkit-learn などのライブラリを使って文書分類に挑戦してみましたが、Pythonにとらわれなければ他の選択肢が考えられました。

Facebookが開発しているOSSのfastTextや、GoogleのサービスであるGoogle Natural Language APIAWSのサービスであるAmazon Comprehendなどを利用するともっと簡単にテキスト分析ができるかもしれません。

fasttext.cc

cloud.google.com

aws.amazon.com

参考文献

以下の記事を大変参考にさせていただきました。深く感謝いたします。

qiita.com

qiita.com