7839

雑草魂エンジニアブログ

Bot と一緒にインタラクティブに学ぶ Python 入門 〜 GitHub Learning Lab の Introduction to Python を受講してみよう

GitHub Actions を学ぶときに「GitHub Learning Lab」を使うと便利であると、カックさん @kakakakakku に教えてもらった。

その「GitHub Learning Lab」の中に「Introduction to Python」コースなるものを発見した。これから Python に挑戦したいと思っていた方は是非チャレンジしてみて欲しい。

lab.github.com

GitHub の流れに沿って行うので、GitHub の操作に関しても実践を通して学ぶことができる。また、個人的な感想としては、Botインタラクティブに対話ができるので、やっていて楽しかった。ただ、本コースに関しては、プログラミングが全くの初心者で挑戦するにはハードルが高い気がした。コードに関する説明が少ないので、Python 以外の他の言語をやったことがあり、Python に初めて触れる方にとってはいいコースであると思えた。実際に、Python のコードに触れて、体験してみるにはいい教材であると思えた。

Introduction to Python とは

「Introduction to Python」は GitHub Learning Lab が提供する Python の入門コースである。現在は日本語翻訳がなく、英語のみではあるが、ステップごとに非常にわかりやすい構成になっているので、英語が少し読めるレベルでも十分に最後まで出来る。以下のように、Step 1 ~ 7 で構成されている。

  • Step 1 : Set up your environment
  • Step 2 : Hello World
  • Step 3 : Change the primary function
  • Step 4 : Read a file into an array
  • Step 5 : Get the last element of an array
  • Step 6 : Retrieve a random quote
  • Step 7 : Explore Python on your own

GitHub の issue に課題が追加されて、Bot と対話しながら、解決していくような流れで進める。 最終的には、テキストファイルからランダムで文章を出力することができる Python のプログラムを作ることができる。

Setup

まず「Start free course」ボタンを押してセットアップを行う。(事前に、GitHub へのサインインが必要となる。)本コースで使う GitHub リポジトリの公開範囲を選択する必要があり、私の場合は Public しか選択できなかったので、そのままで進めた。すると、自動的に python-random-quote が作られる。

f:id:serip39:20200810224507p:plain

そして、bot から Step1 で何をすべきか、丁寧に説明が書かれた issue が追加されているので、それに従って進めていく。

f:id:serip39:20200810225244p:plain

Step 1 : Set up your environment

まず、Python の実装を始める前に、開発環境のセットアップが必要なので、STEP 1 ではまず環境設定を行う。確認すべき項目は以下の3つである。

  1. Python 3 がインストールされているか
  2. Git がインストールされているか
  3. 本コースのリポジトリがローカルにクローンされているか

バージョンの確認方法、ダウンロード先含め、全て丁寧に記載されているので、それに従って進める。以下が、私のローカルの環境設定であった。

$ python3 -V
Python 3.7.7
$ git --version
git version 2.27.0

問題なければ、issue をクローズすることで、次に進むことができる。GitHub の詳細な操作説明はないので、前提コース「Introduction to GitHub」コースを受講しておくことをオススメする。

Step 2 : Hello World

実際に、Python のプログラムの動作確認を行う。クローンしたファイルの一部のコメントアウトを外して、実行することで、実行結果が表示されれば OK である。

変更箇所をコミットして、GitHub に push することで、次の課題が bot から告げられる。Git の操作が始めての人でも、手順通りにやればできるよう、丁寧にコマンドが書いてあるので安心してほしい。

Step 3 : Change the primary function

def main():
  print("Keep it logically awesome.")

if __name__== "__main__":
  main()

次に、現在のコードでは、関数名が main となっているので、この関数名を primary に変更する課題が出される。この章では、関数の関連性、紐付けを確認することができるようになっている。

変更が完了したら、GitHub に push して完了だ。

Step 4 : Read a file into an array

ここからが、本題のプログラムである。まず、先程実行した2行目を再度コメントアウトして、実行されないようにする。次に、4行目以降のコメントアウトを外す。

f = open("quotes.txt")
quotes = f.readlines()
f.close()
print(quotes)

上記のコードを実行することで、テキストファイルを読み込み、読み込んだ結果を出力することができる。読み込んだ文字列は配列として取り込まれているので、最初の一行のみを表示するようにプログラムを変更して、実行する。

実行した結果を issue のコメント欄に貼ると、Bot が反応して、次の課題に進むことができる。

Step 5 : Get the last element of an array

先程は、最初の行を表示したので、次は最後の行を表示してみましょうという課題だ。 配列操作の課題である。解決方法は以下の2パターンである。

  1. テキストファイルの行を数える。ただし、最初の行が「0行目」であることに注意が必要であると記載されている。
  2. 負の数を指定する。(こちらはテキストには記載されていないが、調べてみて欲しい。)

変更して、実行した結果を issue のコメントに貼ると、Bot が反応してくれ、次の課題に進むことができる。

Step 6 : Retrieve a random quote

次に、乱数を発生させて任意の行を表示させるプログラムに変更する。

そのために、random モジュールを読み込み、処理を行うことができるよう、コードを変更する。

変更が完了して、無事に実行できれば、push して完了である。

ここまででコードの説明は終わりとなる。

Step 7 : Explore Python on your own

発展課題として、以下が提示されている。

  • テキストファイルに文章を追加する
  • 一度に複数行の出力をする
  • 出力時に、改行コードを削除する
  • ファイルの書き込みについて学び、プログラムで引用符を追加する

Step 7 に関しては、現時点では、回答がない形になっている。

まとめ

Botインタラクティブに、一緒に学ぶ新感覚はいい体験であった。一歩一歩確実に進める形はとても良かったように思う。「GitHub Learning Lab」は Git に限定せず、汎用的な学習プラットフォームになりつつあるようだ。今後も要チェックしていきたい。また、Issue や Pull Request など GitHub の機能を活用して、誰でもコースを作って公開することが可能なので、是非自分もコンテンツ作成に挑戦したいと思えた。

それでは、ステキな開発ライフを。

関連記事

GitHub Learning Lab」の GitHub Actions は以下をどうぞ。 kakakakakku.hatenablog.com

【JS】更新頻度が高いデータ構造に最適なMap オブジェクトを試した

最近、あるプロジェクトで初めて Map オブジェクトを使うことになり、これまで使ったことがなかったので調べてみました。備忘録として残しておく。

Map オブジェクトとは

developer.mozilla.org

Map オブジェクトとは、名前にもあるようにオブジェクトである。ES2015(ES6)から導入され、キーと値のペアを保持することができるオブジェクトである。

こう聞くと、Object と同じではないか?と思う。どちらも、キーと値のペアでデータを保持して、必要に応じてデータの出し入れが可能である。

違いとしては以下が挙げられる。

Map Object
キーの型 関数、オブジェクトなどの何でもいい String または Symbol のみ
キーの順序 挿入順 キーがStringの場合のみ、挿入順
素数 'size' プロパティで確認できる 素数を数える必要がある
反復処理 反復可能(iterable)プロトコルをもつ反復可能オブジェクト キーを指定して反復処理を行う必要がある

反復処理に関しては、下記の使い方で、反復処理が簡単に実装可能であることを確認してほしい。

iterable に関しても、詳細は公式を確認してほしい。 developer.mozilla.org

使い方

Mapの作成

const mapObj = new Map()
// 初期値を設定する場合
const mapObj = new Map([['key1',  'value1'], ['key2', 'value2']])

初期値は、キーと値のペア(['key', 'value'])の配列を渡すことで設定することができる。

要素の追加

Map.prototype.set(key, value)key に対する value を Mapオブジェクトに追加することができる。同じ key を追加した場合は、値が上書きされる。

mapObj.set('key3', 'value3')

// 複数追加したい場合、メソッドチェーンを利用する
mapObj.set('key3', 'value3')
     .set('key4', 'value4')

要素の取得

Map.prototype.get(key) key を指定して、値を取得することができる。

const output = mapObj.get('key3')
console.log(output)  // value3

要素の削除

Map.prototype.delete(key) key を指定して、削除することができる。

mapObj.delete('key3')
console.log(mapObj.get('key3'))  // undefined

反復処理

以下の2つのパターンがある。

  1. Map.prototype.forEach() を使う場合
  2. 反復可能オブジェクト(Iterator)を使う場合
    • Map.prototype.entries() : [key, value]の配列を挿入順で返す
    • Map.prototype.keys() : 各要素の key を挿入順で返す
    • Map.prototype.values() : 各要素の value を挿入順で返す
mapObj.forEach((value, key) => {
  console.log(key + ' = ' + value)
})

for (let [key, value] of mapObj.entries()) {
  console.log(key + ' = ' + value)
}

その他の便利メソッド

map-like に関して

これまで、Map オブジェクトをみてきたが、反復可能オブジェクト(Iterator)は生成コストがかかり、パフォーマンスに影響してくることが言われているらしい。

そこで、反復可能オブジェクト(Iterator)ではなく、配列を返すのみのMapのようなオブジェクトが生成できる、map-like というモジュールがある。

github.com

もしパフォーマンスを気にされる場合は、こちらを使うことも検討してみてはどうだろうか。(ちなみに、今回のプロジェクトではこちらを使っている。)

まとめ

Map オブジェクトに関して、整理を行った。キーと値のペアを頻繁に追加したり削除したりする場合は、Objectよりも、Map のほうが最適とのことだ。

それでは、ステキな開発ライフを。

【Python】urllib.request / xml.etree.ElementTree を用いてHTTP API を利用する(Basic認証/POST/x-www-form-urlencoded/XML)

Python で HTTP API を利用する場合に、いつもの application/json ではなく、POST のコンテンツタイプが application/x-www-form-urlencoded で、response が XML で返却される API があり、標準モジュールを調べながら実装したので、備忘録として残しておく。

Python Version:3.8.5

urllib.request

Python から HTTP API を利用する場合、requests のような便利なモジュールがあるが、標準ライブラリーである urllib.request でも十分だと思い、今回は標準モジュールを使うこととした。

docs.python.org

POST(application/x-www-form-urlencoded)

項目 設定
認証 Basic認証
コンテンツタイプ x-www-form-urlencoded
レスポンス XML
import urllib.request
import base64
import ssl
url = 'https://<---request URL--->'
user = '<---user--->'
password = '<---password--->'
basic_auth = base64.b64encode('{}:{}'.format(user, password).encode('utf-8'))
req_header = {
    'Authorization': 'Basic ' + basic_auth.decode('utf-8'),
    'Content-Type': 'application/x-www-form-urlencoded'
}
req_data = urllib.parse.urlencode({
    'name': 'TEST MAN',
    'context': 'hogehoge'
})
req = urllib.request.Request(url=url, data=req_data.encode('ascii'), method='POST', headers=req_header)
context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
try:
    with urllib.request.urlopen(req, context=context) as response:
        print(response.read())
except urllib.error.URLError as e:
    print(e.reason)

x-www-form-urlencoded は、"name=TEST MAN&context=hogehoge" のような形で、キーと値は「=」でキーと値の組となり、「&」で区切られてエンコードされる。また、キーや値の英数字以外の文字は、パーセントエンコーディングされる。

urllib.parse.urlencode({ 'name': 'TEST MAN',  'context': 'hogehoge'})
> name=TEST MAN&context=hogehoge

このようにエンコードすることで、文字列となる。ただし、Request.data は、Byte型かファイルオブジェクトでないといけないため、byte型に変更している。

data=req_data.encode('ascii')

また今回、以下のようなSSL認証エラーが発生した。

urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed

SSLContext を使うことで解消できたので、追加している。

POST(application/json

import urllib.request
import json
url = 'https://<---request URL--->'
req_header = {
    'Content-Type': 'application/json',
}
req_data = json.dumps({
    'name': 'TEST MAN',
    'context': 'hogehoge'
})
req = urllib.request.Request(url=url, data=req_data.encode('ascii'), method='POST', headers=req_header)
try:
    with urllib.request.urlopen(req) as response:
        print(json.loads(response.read()))
except urllib.error.URLError as e:
    print(e.reason)

GET

QueryString を使って、リクエストパラメータを送る場合は、urllib.parse.urlencode を利用する。

import urllib.request
url = 'https://<---request URL--->'
params = {
    'foo': 123,
}
url_params = '{}?{}'.format(url, urllib.parse.urlencode(params)
req = urllib.request.Request(url=url_params, method='GET')
try:
    with urllib.request.urlopen(req) as response:
        print(response.read())
except urllib.error.URLError as e:
    print(e.reason)

xml.etree.ElementTree

XML を操作する場合は、xml.etree.ElementTree を使う。便利なモジュールとしては、xmljsonxmltodict などがある。

docs.python.org

XMLの読み込み

import xml.etree.ElementTree as ET
# ファイルから読み込む場合
tree = ET.parse('file_name.xml')
root = tree.getroot()
# 文字列 or バイト型のXMLを読み込む場合
root = ET.fromstring(xml)

データの読み取り

メソッド名 操作
.tag タグの名前を読み取る
.attrib 属性のデータを読み取る
.text テキストデータを読み取る

子ノードの探索に関しては、様々なメソッドがあるので、Element オブジェクト を確認して欲しい。

array = []
for child in root.iter('data'):
    array += [{el.tag: el.text for el in child }]
print(array)

上記では、<data> 配下の要素のタグ名をkey、テキストデータをvalueとして、辞書型とし、XMLを辞書配列に変更した例である。

まとめ

便利なモジュールがたくさんある中で、今回Pythonの標準モジュールを調べて使ってみた。標準モジュールで十分実装できると思えた。参考にしてもらえると嬉しい。

それでは、ステキな開発ライフを。

VSCode + Drow.io で、図形入りドキュメントを作成する方法

VSCode拡張機能 Draw.io Integration がリリースされ、VSCodeで作画ができるようになったということで、早速導入して使ってみたので紹介する。

チーム開発の中で、フロー図やドキュメントをコードと一緒に管理して共有できることはすごく便利だと感じている。

Draw.io とは

Draw.io は、フローチャート、プロセス図、UML 図、ER モデル、ネットワーク図などを作成できる、無料のWebアプリケーションである。 作成した図は xml ファイルとして保存される。もちろん画像やPDF形式での出力も可能である。

app.diagrams.net

私も様々な場面で、Draw.io を愛用してきた。様々な便利なテンプレートがあり、操作も直感的でわかりやすい。そして、無料で使えるのは本当に有り難い。

そんな Draw.io が VSCode拡張機能としてリリースされた。

marketplace.visualstudio.com

導入方法

VSCode拡張機能検索窓で「Draw.io Integration」と検索して、インストールをするだけである。(もちろん、Draw.io Integration のページから「install」ボタンを押してもいいが、VSCode内でやるのが一番簡単かと思う。)

f:id:serip39:20200807004101p:plain

インストール後は、一度再起動することをオススメする。

使い方

拡張子を以下の4種類にすることで、自動で描画ツールが VSCode で起動する。

作成した図を Markdown で書いたドキュメントに埋め込むことを想定した場合、drawio.svg で作成するのがオススメである。(公式にも記載があるが、pngよりもsvgのほうが画質が損なわれず見やすいのでオススメされている。)

(※注意)
画像として挿入する場合は、キャンバスの大きさを調整する必要がある。デフォルトでは、A4サイズになっているため、画像サイズが大きすぎて、ドキュメントファイルに表示されない場合があるので、画像サイズに合わせてキャンバスのサイズを調整してみて欲しい。

キャンバスの調整は、FIle > Page Setup...より変更可能である。

f:id:serip39:20200807012255p:plain

Markdown ファイルに作成した図を埋め込む場合は、通常どおり ![代替テキスト](画像のファイルパス) で記述する。

もちろん、README にも追加できる。

f:id:serip39:20200807012816p:plain

また 通常のWEBアプリケーションとは異なり、XML ファイルを直接編集することも可能で、変更が図にリアルタイムに反映される。

https://github.com/hediet/vscode-drawio/raw/master/docs/drawio-xml.gif

まとめ

文章をマークダウン、図形をDraw.ioを使ってドキュメント化することで、ソースコード含めすべてを VSCode および Git で管理することができ、非常に便利である。図があることで、ドキュメントのわかりやすさも向上するので、ドキュメントに図を挿入することはオススメである。また、頭の中を整理するために、描画することも個人的にはオススメである。

それでは、ステキな開発ライフを。

画面分割可能なMacアプリ「Spectacle」

最近、新しい職場の Mac をセットアップした際に、新しく入れたアプリで作業効率が上がったのでご紹介。

今回紹介するアプリは、自由自在に画面分割可能なアプリ「Spectacle」である。

もしまだ Mac に入れていない人は是非参考にして欲しい。

Spectacle とは

「Spectacle」はキーボードショートカットで、簡単に画面を分割することができるアプリである。

Windows の場合、Win+矢印キーを押すことで、アクティブなウィンドウをスナップ表示できる。

Mac でも、デフォルトの機能である Split View を使うことで左右に分割することは可能である。

support.apple.com

ただし、それぞれの画面をフルスクリーンにして、縮小表示して移動させるなど、Windowsのようにコマンドのみでできない。

それを解決してくれたのが、「Spectacle」である。 現在は、オープンソースソフトウェア(OSS)として開発されており、基本的に全ての機能を無料で使用できる。

プログラマーやブロガーの皆さんは、よく2画面で作業をすることがあると思うが、そんな方にオススメのアプリである。

インストール方法

「Spectacle」のトップページにアクセスする。

www.spectacleapp.com

f:id:serip39:20200805214437p:plain

「Download Spectacle」をクリックすることで、ファイルがダウンロードされるので、そのファイルをクリックし展開する。

「Spectacle.app」がファインダーに表示されたら、アプリケーションフォルダーに移動する。

アプリケーションを起動してみる。

f:id:serip39:20200805215228p:plain

画面分割のためMac OSから操作の許可を得る必要があるので、「Open System Preferences」をクリックする。

f:id:serip39:20200805215717p:plain

セキュリティとプライバシーが開くので、左下の鍵のアイコンをクリックして、Macのパスワード要求に従い、入力する。
アクセシビリティ」に対して、「Spectacle.app」を許可してあげれば、設定完了。

Macの上部のメニューバーに「眼鏡」アイコンが表示されていればバッチリ。

設定方法

ショートカットコマンドに関しても、メニューバーの「眼鏡」アイコンをクリックすることで確認することができる。

デフォルトの設定では、「Option + Command + 矢印」で画面分割が可能である。

ただし、ここで問題が発生した。

Chromeの左右のタブ切り替えのショートカットキーと同じせいで、Chromeのショートカットキーが使えなくなるという事態。

そこで、Spectacleの設定を以下のように変更した。

「Shift + Command + 矢印」

設定の変更は、メニューバーの「眼鏡」アイコンをクリックして、「Preference」から変更可能である。

まとめ

ショートカットだけで画面分割ができる、一見ただそれだけのアプリであるが、これがまさに便利なのである。

是非、まだインストールしていない方は、コマンドだけで使える画面分割の快適さを味わって欲しい。

Mac のセットアップを機会に、私も導入してみて、かなり便利だったので、今回紹介してみた。

それでは、快適な開発ライフを。