できる 仕事がはかどるPython自動処理 全部入り。の第4刷が決定しました

昨年、ビジネスパーソン向けの Python 本を執筆したことを書きました。

t2y.hatenablog.jp

おかげさまでまだ売れ行きは好調なようです。本書を購入していただいた方々、ありがとうございます。

このたび、第4刷の重版が決定しました。

【第4刷】3月16日(月)重版出来

book.impress.co.jp

Chapter 10 「065 Web ページを Selenium で操作する」の修正について

第4刷で本節の一部のコードが修正されます。 Selenium という Web ブラウザを操作するライブラリの使い方を紹介している節です。

これまでは Yahoo! JAPAN のトップページを題材として Selenium の操作を説明していました。

PC 版 Yahoo! JAPAN のトップページを 2019 年 10 月 1 日に刷新、 ... (中略) ... Yahoo! JAPAN トップページは 2008 年 1 月 1 日に大規模なリニューアルを行いました。その頃からある程度の改修はあったものの、基本的にはコードの継ぎ足しで修正を加えている状態でした。

techblog.yahoo.co.jp

なんと11年間変わらなかったトップページが2019年10月1日に大きな改善が入り、トップページの HTML の構造が変わってしまい、本書で説明している方法では動作しなくなってしまいました。

そこで第4刷では次のように Wikipedia のトップページに対して同じ操作を行うように変更しています。 申し訳ありませんが、第1-3刷を購入された方は次の内容に読み替えて Selenium の操作を確認してください。

変更した内容

まず、Wikipediaトップページの URLを指定してブラウザに表示させます。get()というメソッドを使います。

>>> driver.get("https://ja.wikipedia.org/")

f:id:t2y-1979:20200229144421p:plain

検索語として「Python」と入力します。検索ボックスには searchInput というid属性が付与されているのでCSSセレクターで指定して、send_keys()でキー入力を送信します。

>>> driver.find_element_by_css_selector("#searchInput").send_keys("Python")

f:id:t2y-1979:20200229144504p:plain

検索候補ウィンドウの検索ボタンにはid属性 searchButton が付与されているので、同様にCSSセレクターで指定して、click()でクリックします。

>>> driver.find_element_by_css_selector("#searchButton").click()

続けて、ブラウザの「戻る」を行ってWikipediaのトップページに戻ったあとに、"ログイン"というリンクを開いてみましょう。

>>> driver.back()
>>> driver.find_element_by_link_text("ログイン").click()

ビジネスPythonを学ぶ会の活動と slack の紹介

本書の読者サポートも兼ねて私が神戸で運営しているコミュニティがあります。 このコミュニティは難しいことを扱うわけではなく、またすぐに業務で役に立たないかもしれませんが、コミュニティとして長く続けられることだけを目標にしています。Python で困ったときに気軽に相談できる場になればいいなと思います。

bizpy.connpass.com

本書の対象読者と同様、Python 入門を終えたばかり初学者、さらに IT エンジニアではない次の方々を対象としています。

いまのところ、月1回の勉強会を開くことを予定しています。地理的に参加できない方もいるでしょうからオンラインでのコミュニケーションが取れるように bizpy.slack.com を開設しています。興味のある方はこちらの 招待リンク からご参加ください。

いまは Excel ファイルを操作する openpyxl ライブラリの操作について取り上げています。そうすると、プログラマーではないけれど、企業でデータ分析の実務を行っている方々が参加してくれます。参加者の実際の実務で行っている内容をみんなで共有したり、参加者が書いたコードをもとにレビューしたり、私が開発やデバッグに役立つ手法を紹介したりといった、そういうゆるい感じの勉強会をしています。

今後も勉強会や読者サポートの過程でお伺いした内容や気づきを留めていき、いつか本書を改訂できる機会ができたときに活かせるように努めていきたいと思います。

まとめ

本書の出版を契機にして、これまで私が接点のなかった方々と Python プログラミングを通してお話する機会が増えました。

私自身、プログラマーとして10年以上働いてきて、ちょうどいまキャリアの棚卸しをしている時期です。今後は培ってきたプログラミングのスキルを活かして世の中の役に立つプロダクトやビジネスを創造することにも挑戦していきたいと考えています。ビジネスパーソンの方々が普段行っている業務や課題意識を知る機会があることは、私にとっては新鮮で興味深いものです。

またプログラミングできる人が増えること自体もいまの世の中にとっては良いことだろうと私は考えています。

リファレンス

t2y.hatenablog.jp

できる 仕事がはかどるPython自動処理 全部入り。の第3刷が決定しました

先日、ビジネスパーソン向けの Python 本を執筆したことを書きました。

t2y.hatenablog.jp

おかげさまで書店ならびにオンライン書店でも好調な売れ行きであるそうです。本書を購入していただいた方々、ありがとうございます。

このたび、第3刷の重版が決定しました。

【第3刷】9月2日(月)重版出来

book.impress.co.jp

オンライン書店による不評から始まった読者サポート

本書は発売当初からリアル書店では好調な売れ行きであると聞いていたものの、オンライン書店では微妙な状況でした。それはおそらく INTERNET Watch での書籍紹介の記事が変なバズり方をしたせいだと私は考えています。

internet.watch.impress.co.jp

本書の対象読者は Python 入門を終えたばかり初学者、さらに IT エンジニアではない次の方々を対象としています。

書名から誤解を招きやすい点や RPA の気運が高まりつつある背景の中、INTERNET Watch の記事をみて (中身を確認せずに) IT エンジニアの方々もオンライン書店で購入された方が多かったのではないかと推測します。

Amazon のカスタマーレビューを時系列にみていただければわかりますが、当初は本書の内容にがっかりしたレビューが多かったです。著者からすると、意図した対象読者へ届いていないことを歯がゆく思ったこともありました。とはいえ、経緯がどうであっても出版してしまったものはしょうがないのでできる範囲でサポートをしようと、身近なところで読者サポートのための勉強会を隔週で開催してきました。

bizpy.connpass.com

回を重ねるごとに勉強会のメンバーも少しずつ増えてきたこともあり、「ビジネスPythonを学ぶ会 (bizpy)」の slack も準備しているところです。いまのところ、読者サポートの勉強会は関西でしか開催できません。もしオンラインでもよいので本書の内容についてやり取りしたいという方は connpass の「ビジネスPythonを学ぶ会」のグループメンバーに登録しておいてください。後日、こちらの準備が整い次第、bizpy slack への招待リンクをグループメンバーへ送る予定です。

さらに Python イベントにも登壇して本書はビジネスパーソンやノンプログラマー向けの、Python を入門を終えた方々を対象としていると訴えることにしました。そのときの登壇資料が次になります。

www.slideshare.net medium.com

どんな理由であれ、本書を手に取っていただける読者が増えることは著者にとって嬉しいことではありますが、必要のない人にまで届けようとは思いません。今後も本書はビジネスパーソンやノンプログラマー向けの書籍であることを訴求していこうと思います。

そういった活動の成果が出てきたのか、2019-07-13 時点では 2.7 だったカスタマーレビューも本日時点で 3.1 まで上がりました。ここ最近は本書の対象読者である方々によるレビューが続いているおかげだと考えています。

f:id:t2y-1979:20190812134943p:plain
2019-08-12 時点での Amazon カスタマーレビュー

またレビューの良し悪しに関わらず、レビューを投稿していただいた読者の方々には感謝を申し上げます。よいレビューは著者にとって励みになりますし、わるいレビューは気づきを得られるのでどちらも次の行動への取っ掛かりになります。

例えば、わるいレビューから得た気づきで書いた補足記事が次になります。残念ながら重版となる第3刷ではこの補足記事を追加することはできませんでした。しかし、この補足記事へのリンクを「ここもポイント」というコラム形式で「Chapter 8 テキストデータの処理」の最後に追記しました。

t2y.hatenablog.jp

今後も勉強会や読者サポートの過程でお伺いした内容や気づきを留めていき、いつか本書を改訂できる機会ができたときに活かせるように努めていきたいと思います。

重版情報をスクレイピングしてみよう

第3刷の発売が決定しましたという案内だけではおもしろくないので本書の内容でできることの宣伝も少し書いてみます。丁寧な説明は意図的に省きますのでもう少し詳しい説明を読みたくなったら本書の購入を検討してください。

重版情報はインプレスさんのスタッフブログに公開されていますが、どうもこのサイトは RSS が提供されていないようです。

book.impress.co.jp

重版情報をチェックしたい方がいるかどうかわかりませんが、こういったときは Web スクレイピングすることでほしい情報を取り出すことができます。本書の「062 Web ページから要素を取り出す」のサンプルコードを応用して挑戦してみます。また本書の「061 Web スクレイピング」の節にある注意事項も書いておきます。スクレイピングに慣れていない方は、スクレイピングを行うときのマナー、約束事項として次のことを必ず守るようにしてください。

  1. 取得したデータは個人的に参照するのみに留める
  2. スクレイピング禁止となっていないかWebサイトの規約を確認する
  3. 大量のリクエストを送らない

本稿で紹介するスクレイピングのサンプルコードは次の URL からダウンロードできます。

CSS セレクターを取得する

Google Chrome (以下Chrome) に限った話ではありませんが、最近の Web ブラウザには開発者のデバッグを助けるためのツールが標準でインストールされていてすぐに使える状態になっています。本書では Chrome を使って説明しているので同様に Chrome を使います。インプレスさんのスタッフブログを Chrome の開発者ツールを使って HTML の要素を表示させたものが次になります。

f:id:t2y-1979:20190812151227p:plain
Google Chrome の開発者ツールを使って調べる

h2 や div といった HTML タグの構造や CSS の class としてどのようなものが設定されているかがすぐにわかります。

本のタイトルと重版についての情報を書いているところが離れているのでそれらを含む上位の div.block-book-detail までの CSS セレクターを Chrome 機能で取得します。

body > div.block-wrap > div.block-content > main > div > div:nth-child(3) > div.block-book-detail-box-body.module-usr-text > div.block-book-detail

Beautiful Soup の Tag オブジェクトを使う

HTML の要素を取り出すために本書では Beautiful Soup というツールを使います。Beautiful Soup で CSS セレクターを用いると Tag オブジェクトが返されます。先ほどの CSS セレクターで取得した Tag オブジェクトが detail にセットされます。そこからさらに CSS セレクターを指定して必要な要素のみを取り出します。

    hrefs = detail.select('h2 > a')
    reprint_messages = detail.select('div.module-book-copy > b')

このとき hrefsreprint_messages は次のようなリストが返されます。

ipdb> pp hrefs
[<a href="https://book.impress.co.jp/books/1118101147" title="できる 仕事がはかどるPython自動処理 全部入り。">◆ できる 仕事がはかどるPython自動処理 全部入り。</a>,
 <a href="https://book.impress.co.jp/books/1119600001" title="ねじ子のヒミツ手技#">◆ ねじ子のヒミツ手技#</a>,
 <a href="https://book.impress.co.jp/books/1119600002" title="ねじ子とパン太郎のモニター心電図 改訂版">◆ ねじ子とパン太郎のモニター心電図 改訂版</a>]
ipdb> pp reprint_messages
[<b class="module-book-price" style=" font-size: 120%; border: 0px; ">【第3刷】92日(月)重版出来</b>,
 <b class="module-book-price" style=" font-size: 120%; border: 0px; ">【第4刷】92日(月)重版出来</b>,
 <b class="module-book-price" style=" font-size: 120%; border: 0px; ">【第2刷】92日(月)重版出来</b>]

個別に要素のリストを取得できました。これらの情報を一緒に扱いたいとき、方法はいくつかありますが、zip() という組み込み関数で組み合わせるのがシンプルに表現できます。

ipdb> pp list(zip(hrefs, reprint_messages))
[(<a href="https://book.impress.co.jp/books/1118101147" title="できる 仕事がはかどるPython自動処理 全部入り。">◆ できる 仕事がはかどるPython自動処理 全部入り。</a>,
  <b class="module-book-price" style=" font-size: 120%; border: 0px; ">【第3刷】92日(月)重版出来</b>),
 (<a href="https://book.impress.co.jp/books/1119600001" title="ねじ子のヒミツ手技#">◆ ねじ子のヒミツ手技#</a>,
  <b class="module-book-price" style=" font-size: 120%; border: 0px; ">【第4刷】92日(月)重版出来</b>),
 (<a href="https://book.impress.co.jp/books/1119600002" title="ねじ子とパン太郎のモニター心電図 改訂版">◆ ねじ子とパン太郎のモニター心電図 改訂版</a>,
  <b class="module-book-price" style=" font-size: 120%; border: 0px; ">【第2刷】92日(月)重版出来</b>)]

あとは出力するときに Tag オブジェクトから必要な属性を指定するだけです。

最終的なサンプルコードは次の通りです。

import requests
from bs4 import BeautifulSoup

page_data = requests.get('https://book.impress.co.jp/staff_blog/').text
page = BeautifulSoup(page_data, 'lxml')
details = page.select("""
body > div.block-wrap > div.block-content > main > div > div:nth-child(3) > div.block-book-detail-box-body.module-usr-text > div.block-book-detail
""")

for detail in details:
    hrefs = detail.select('h2 > a')
    reprint_messages = detail.select('div.module-book-copy > b')
    hrefs_and_reprints = zip(hrefs, reprint_messages)
    for href, reprint in hrefs_and_reprints:
        print(f'{href["title"]}: {reprint.text}')

実行結果は次の通りです。

$ python impress_book_reprint_list_all.py
できる 仕事がはかどるPython自動処理 全部入り。: 【第3刷】9月2日(月)重版出来
ねじ子のヒミツ手技#: 【第4刷】9月2日(月)重版出来
ねじ子とパン太郎のモニター心電図 改訂版: 【第2刷】9月2日(月)重版出来

私が興味があるのは「できるPy」のみなので、さらに if 文で条件を限定することでほしい情報のみを絞り込めます。

    for href, reprint in hrefs_and_reprints:
        if href["title"] == 'できる 仕事がはかどるPython自動処理 全部入り。':
            print(f'{href["title"]}: {reprint.text}')

実行結果は次のようになります。

$ python impress_book_reprint_list_dekiru.py
できる 仕事がはかどるPython自動処理 全部入り。: 【第3刷】9月2日(月)重版出来

まとめ

本書の「062 Web ページから要素を取り出す」のサンプルコードを応用して RSS 情報のないサイトのページを取り出してみました。

本書で扱う「自動化」というのはこの程度の内容を十数行から数十行のサンプルコードで解説します。このぐらいのレベル感で目次にある内容の、Python プログラミングやツール・ライブラリの使い方を知りたいという方にとっては本書は役に立つでしょう。もしくは、このぐらいの内容なら自分で調べてすぐに実装できるという方であれば本書は不要になります。

どちらとも言えない方はぜひリアル書店へ足を運び、そこで中身を少し読んでみて、その直感で選択していただければと思います。

リファレンス

少し古いバージョンですが、Beautiful Soup ドキュメントの日本語訳もありました。

kondou.com

できる 仕事がはかどるPython自動処理 全部入り。 (「できる全部入り。」シリーズ)

できる 仕事がはかどるPython自動処理 全部入り。 (「できる全部入り。」シリーズ)

Python で Unicode 正規化 NFC/NFD の文字列を扱う

先日、ビジネスパーソン向けの Python 本を執筆したことを書きました。

t2y.hatenablog.jp

本稿では本書のことを「できるPy」と呼びます。

Amazon でいくつかカスタマーレビューもいただいて次のコメントをみつけました。

python3.7 対応ということで、pathlib を使ってる点が(古いpython は切り捨てる!的なところは)潔いと言えば潔いし、日本語のファイル名にも気を配っている記述はオライリーに期待するのは酷なところもある。でもこの本でもNFD問題は全くの記述無し。だめだろ、それじゃ。

Amazon CAPTCHA

まさに仰る通りです。執筆時にそのことに気づかずご指摘いただいてありがとうございます。

ここでご指摘されている NFD 問題というのは、ファイル名のみに限った問題ではなく、Unicode文字集合を扱ってエンコード/デコードするときに発生する問題です。ASCII 文字しか扱わない開発者が書いたコンテンツとの差別化を図るという意味でも付加価値になり得るコンテンツだと私も思います。

本稿では「できるPy」に掲載できなかった NFC/NFD 問題について説明しようと思います。私の一存では決められませんが、本書を改訂できるタイミングがあれば、出版社と相談して本稿の内容も追加してもらうように働きかけようと考えています。

本稿で紹介するサンプルデータならびにサンプルコードは次の URL からダウンロードできます。

NFC/NFD 問題とは

Unicode は世界中のすべての言語で使われる文字を扱う文字集合です。Python は内部的に Unicode で文字列を扱います。例えば、UTF-8エンコードされたファイルの内容を読み込むコードが次になります。

import sys

filename = sys.argv[1]
with open(filename, encoding='utf-8') as f:
    for line in f:
        print(line.strip())

Unicode では1つの文字を表すのに複数の文字を組み合わせることができます。そして、同じ文字が別々の表現だと検索や置換などに不都合があるのでどれか1つの表現に統一することを 正規化 と呼びます。その正規化形式の名前の頭文字をとって NFC、NFD と呼びます。

  • NFC: Normalization Form Canonical Composition (合成済みの文字)
  • NFD: Normalization Form Canonical Decomposition (複数文字を結合した文字列)

言葉だけではわかりにくいので実際にその違いをサンプルデータとともに説明します。いま NFC/NFD で正規化されたテキストファイルを前述したプログラムを使って中身を表示してみます。

実行結果。

$ python3 read_file_and_print.py NFC_sample1.txt
プログラミング

$ python3 read_file_and_print.py NFD_sample1.txt
プログラミング

どちらも「プログラミング」と表示されました。OS 環境や OS バージョンによって正しく表示されない可能性もあります。私の環境 (macOS 10.14.4) では見た目上は全く同じに表示されます。

このとき変数 line には UTF-8 でデコードされて Unicode の文字列がセットされます。次に NFC/NFD 問題をイメージしやすいように Unicode の文字列を文字単位で扱うサンプルを紹介します。

import sys
import unicodedata

def show_unicode_name(line):
    for char in line.strip():
        name = unicodedata.name(char)
        space = ' '
        if unicodedata.combining(char) != 0:
            space += ' '
        print(f'{char}{space}: {name}')

filename = sys.argv[1]
with open(filename, encoding='utf-8') as f:
    for line in f:
        text = [char for char in line.strip()]
        print(f'文字単位: {text}, 長さ: {len(text)}')
        show_unicode_name(line)

実行結果。

NFC で正規化されたテキストを文字単位で分割して Unicode データベースに登録されている名前を表示する。

$ python3 read_file_and_show_unicode_name.py NFC_sample1.txt
文字単位: ['プ', 'ロ', 'グ', 'ラ', 'ミ', 'ン', 'グ'], 長さ: 7
プ : KATAKANA LETTER PU
ロ : KATAKANA LETTER RO
グ : KATAKANA LETTER GU
ラ : KATAKANA LETTER RA
ミ : KATAKANA LETTER MI
ン : KATAKANA LETTER N
グ : KATAKANA LETTER GU

NFD で正規化されたテキストを文字単位で分割して Unicode データベースに登録されている名前を表示する。

$ python3 read_file_and_show_unicode_name.py NFD_sample1.txt
文字単位: ['フ', '゚', 'ロ', 'ク', '゙', 'ラ', 'ミ', 'ン', 'ク', '゙'], 長さ: 10
フ : KATAKANA LETTER HU
 ゚  : COMBINING KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK
ロ : KATAKANA LETTER RO
ク : KATAKANA LETTER KU
 ゙  : COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK
ラ : KATAKANA LETTER RA
ミ : KATAKANA LETTER MI
ン : KATAKANA LETTER N
ク : KATAKANA LETTER KU
 ゙  : COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK

NFD で正規化された文字列では濁音や半濁音が別の文字として扱われていて、Unicode の文字として数えたときの文字数も異なっていることがわかります。例えば「プ (U+30D7)」と、「フ (U+30D5)」と合成用半濁点 (U+309A) の組み合わせで表す「プ」の文字は Unicode 上では別の文字なのでこの違いにより、検索や置換などで一致しないということが発生します。

このような Unicode における正規化の違いによって起こる問題のことを NFC/NFD 問題と呼ばれたりします。

NFC/NFD 問題が発生する状況

OS によって Unicode の正規化形式が異なります。Windows/Linux では NFC を採用しており、昔の macOS (Mac OS X) では NFD を採用していました。同じプラットフォーム上で日本語ファイル名や日本語のテキストを扱っている分には、この問題に遭遇することは少ないかもしれません。

また macOS では NFD を採用しているという記事をみかけますが、最近の macOSiOS では NFC を使うように変わっているそうです。ファイルシステムが HFS+ から Apple File System (APFS) に置き換えられたときに変わったのかもしれません。私はその背景に明るくないため、詳しい方がいましたら教えてください。

私の環境は macOS 10.14.4 ですが、APFS を使っているせいか、NFCUnicode 正規化が行われます。

$ mount
/dev/disk1s1 on / (apfs, local, journaled)

この NFC/NFD 問題は昔の macOS (Mac OS X) で作られた日本語ファイル名や、Unicode文字集合に用いる符号化方式でエンコードされたコンテンツを Windows/Linux 環境で扱うとき、もしくはその逆のときに発生します。一方で NFD を採用していたときの macOS (Mac OS X) であっても、例えば Web ブラウザからコピペしたコンテンツは NFC で扱われたりして、同じプラットフォーム上でも NFD と NFC が混在してしまうといったことも発生するそうです。そして、見た目上は全く同じ文字にみえるため、この問題に気付くのが難しいというのが NFC/NFD 問題の厄介なところです。

Python で NFD を NFC に正規化する

さて本題です。ここまでで NFC/NFD 問題の概要を説明しました。

Python では標準ライブラリで Unicode データベースを扱うライブラリ unicodedata が提供されています。このライブラリを使うことで Unicode 文字の情報を取得したり、読み込んだ文字列に対して NFC/NFD といった正規化形式の変換をやり直すこともできます。

docs.python.org

unicodedata.normalize() の引数に NFC や NFD といった正規化形式と Unicode 文字列を渡すと変換できます。

unicodedata.normalize('NFC', unistr)

また結合文字かどうかは unicodedata.combining() に文字を渡してゼロ以外が返ってくるかどうかで判断できます。

unicodedata.combining(chr)

次のサンプルコードでは、濁音、半濁音などの結合文字があるかどうかを調べて、結合文字がある場合は NFC に変換します。

import sys
import unicodedata

def is_nfd(line):
    for char in line.strip():
        if unicodedata.combining(char) != 0:
            return True
    return False

def show_unicode_name(line):
    for char in line.strip():
        name = unicodedata.name(char)
        space = ' '
        if unicodedata.combining(char) != 0:
            space += ' '
        print(f'{char}{space}: {name}')

filename = sys.argv[1]
with open(filename, encoding='utf-8') as f:
    for line in f:
        text = [char for char in line.strip()]
        print(f'文字単位: {text}, 長さ: {len(text)}')
        show_unicode_name(line)

        if is_nfd(line):
            print('NFD から NFC への変換')
            converted = unicodedata.normalize('NFC', line)
            show_unicode_name(converted)

実行結果。

$ python3 read_file_and_normalize.py NFD_sample1.txt
文字単位: ['フ', '゚', 'ロ', 'ク', '゙', 'ラ', 'ミ', 'ン', 'ク', '゙'], 長さ: 10
フ : KATAKANA LETTER HU
 ゚  : COMBINING KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK
ロ : KATAKANA LETTER RO
ク : KATAKANA LETTER KU
 ゙  : COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK
ラ : KATAKANA LETTER RA
ミ : KATAKANA LETTER MI
ン : KATAKANA LETTER N
ク : KATAKANA LETTER KU
 ゙  : COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK
NFD から NFC への変換
プ : KATAKANA LETTER PU
ロ : KATAKANA LETTER RO
グ : KATAKANA LETTER GU
ラ : KATAKANA LETTER RA
ミ : KATAKANA LETTER MI
ン : KATAKANA LETTER N
グ : KATAKANA LETTER GU

まとめ

PythonUnicode の文字列が NFC/NFD のどちらの形式で正規化されているか、また別の正規化形式に変換する方法を紹介しました。

最近の macOSNFC を採用していることからいまが過渡期で NFC/NFD 問題は徐々に NFC に統一されていって将来的にはこういった問題が起こらなくなるのかもしれません。一方で NFD という表現形式も Unicode で定義されている仕組みであり、この仕組み自体がなくなるわけではありません。

本稿では濁音・半濁音のみを紹介しましたが、特殊な記号を複数の記号の組み合わせで表現することもできます。Unicode にはこのような表現形式があるというのを覚えておくといつか役に立つことがあるかもしれません。

リファレンス

ja.wikipedia.org

en.wikipedia.org

www.slideshare.net

gihyo.jp

qiita.com

できる 仕事がはかどるPython自動処理 全部入り。を執筆しました

インプレスから「できる」シリーズの Python 版として発売されました。著者の1人として執筆に関わったので紹介します。

book.impress.co.jp

名前が長いので本稿では本書のことを「できるPy」と呼びます。誰も聞いていませんが、ハッシュタグ#dekiru_py です。

経緯

2018年3月頃に知人からビジネスパーソンを対象に本書の監修として企画・構成をしてほしいといった依頼をいただきました。そのとき、書き手はやる気のある若い人たちがたくさんいるからと、私が目次を作って全体の構成をまとめたら誰かがコンテンツを書いてくれて、私は出来上がったコンテンツをレビューするのが主な役割になるのかなと安易に考えていました。

結果的には私が他の執筆者全員に声をかけて書いてもらうようにお願いして、私自身も著者の1人として少なくない割合を執筆しました。

詳細な目次

インプレスサイトでは目次が公開されていません。Amazon のサイトにも章レベルの目次しかありません。店頭で目次チェックするのも面倒だと思うので詳細な目次を書いておきます。目次のタイトルは編集者さんが対象とする読者層、ビジネスパーソンな方々がわかりやすいようにつけてくれました。

次のような「ここもポイント」という見出しでちょっとした小話や発展的なヒントをいくつか書いています。その目次も一緒に含めておきます。

f:id:t2y-1979:20190525120231p:plain:w480

Chapter 1 Pythonのプログラムを利用する前に … 011

Pythonの紹介

  • 001 Pythonがビジネスに役立つってホント? … 012
    • ここもポイント | インデントルールの背景 … 014

実行環境の構築

実行環境の注意点

  • 004 OSによる違いを把握する … 032

Chapter 2 コマンドラインインターフェース … 035

コマンドラインインターフェース

インタラクティブシェル

Chapter 3 サードパーティライブラリのインストール … 059

パッケージマネージャ

  • 011 パッケージマネージャを使ってライブラリをインストールする … 060
    • ここもポイント | その他の処理系 … 061
  • 012 condaを使ったパッケージのインストール … 062
  • 013 pipを使ったパッケージのインストール … 067

Chapter 4 Pythonのおさらい … 069

プログラミング用語

  • 014 覚えておきたいPython&プログラミングの基本用語 … 070

用語と文法

  • 015 Pythonプログラミングの基本 … 074

基本テクニック

Chapter 5 ファイルの操作と圧縮・展開 … 097

ファイル一覧の取得

  • 018 フォルダ内のファイルを一覧表示する … 098
  • 019 特定種類のファイルだけを表示する … 101

ファイルの圧縮/展開

  • 020 ZIPファイルを作成/展開する … 103
  • 021 ZIPファイルに含まれるファイル名を文字化けさせずに表示する … 107
  • 022 ZIPファイルに含まれるファイル名を文字化けさせずに展開する … 116

Chapter 6 画像の加工 … 119

Pillowによる画像加工

  • 023 Pillowを使った画像処理の基本 … 120
  • 024 画像のサイズ変更と切り抜きを行う … 123
  • 025 画像を回転する … 125
  • 026 画像をモノクロにする … 126

画像の連続処理

  • 027 画像のサイズをまとめて調整する … 127

piexif

Chapter 7 CSVファイルの処理 … 137

CSVファイルの読み込み

  • 029 CSVファイルを読み込む … 138
    • ここもポイント | ちょっとした集計にも役立つ関数 … 142
  • 030 読み込んだCSVファイルを1行ずつ処理する … 143
  • 031 ヘッダー行がないCSVファイルを読み込む … 145
  • 032 文字コードを指定してCSVファイルを読み込む … 146

CSVファイルの書き込み

  • 033 CSVファイルを書き込む … 148
  • 034 列の順番を指定してCSVファイルを書き込む … 151
  • 035 インデックス列を出力せずにCSVファイルを書き込む … 152
  • 036 項目(値)にクォートを付けてCSVファイルを書き込む … 153
  • 037 タブ区切りのデータとしてファイルを書き込む … 158
  • 038 読み込んだCSVファイルに列を追加して書き込む … 159
  • 039 JSONデータを読み込んでCSVファイルを書き込む … 160

CSVビューアーの作成

  • 040 横に長いデータを縦向きで表示する … 163
  • 041 複数の値を扱うときに便利な組み込み関数 … 171
  • 042 指定した列番号の情報だけを表示する … 173
    • ここもポイント | 大きなプログラムを作るときのコツ … 174

Chapter 8 テキストデータの処理 … 175

文字列操作

  • 043 文字列の基本的な操作 … 176

正規表現

  • 044 正規表現を使った文字列の扱い … 184
  • 045 正規表現にマッチするすべての文字列を取り出す … 189
  • 046 HTMLファイルからタグを取り除く … 191
  • 047 非構造化テキストをディクショナリにする … 193

テキスト抽出

  • 048 Microsoft Wordからテキスト抽出 … 196
  • 049 Microsoft PowerPointからテキスト抽出 … 202
  • 050 PDFからテキスト抽出 … 207
  • 051 Markdown形式のドキュメントをHTMLに変換する … 215

形態素解析

  • 052 テキストから重要語句を抜き出す … 219

Chapter 9 Microsoft Excelとの連携 … 225

Excelとopenpyxl

ワークブックの操作

  • 054 ワークブックを扱う … 228
  • 055 既存のExcelファイルを読み込む … 230

セルの操作

  • 056 セルを扱う … 234

グラフの作成

  • 057 CSVファイルを読み込んでグラフを作成する … 239

条件付き書式

  • 058 条件付き書式を扱う … 247
  • 059 値や数式を使った条件付き書式を設定する … 254
  • 060 設定済みの条件付き書式を調べる … 257

Chapter 10 Webスクレイピング … 261

Webスクレイピングの概要

Beautiful Soup

  • 062 Webページから要素を取り出す … 264
  • 063 Webページ内の画像を取り出す … 272

Selenium

  • 064 Webブラウザを自動で制御するには … 276
  • 065 WebページをSeleniumで操作する … 279
    • ここもポイント | SeleniumとBeautiful Soupの違いと使い分け … 283

feedparser

  • 066 RSSを利用してニュースを取得する … 284

Chapter 11 Web API … 287

Web APIの概要

  • 067 Web APIとは … 288
    • ここもポイント | Web APIは変化する … 289

Google Sheets API

  • 068 Google Sheets APIの利用準備をする … 292
    • ここもポイント | 鍵ファイルの管理 … 297
  • 069 Googleスプレッドシートを操作する … 299
    • ここもポイント | 鍵ファイルとprepare_credentials関数 … 301

Google Calendar API

複数のWeb APIの組み合わせ

退屈なことはPythonにやらせよう ――ノンプログラマーにもできる自動化処理プログラミング

www.oreilly.co.jp

オライリー・ジャパンさんから2017年6月に出版されています。

本書の依頼をうけたときに出版社の編集者さんから「退屈なことはPythonにやらせよう」がビジネスパーソン向けに人気があるというお話を伺いました。2017年6月の出版で半年しか販売期間がなかったにも関わらず、次の2018年の技術書ランキングではトップ10内に君臨していてその人気ぶりが伺えます。

gihyo.jp www.shoeisha.co.jp

私も技術書ランキングなどで取り上げられているのを見聞きしていたので本の名前は知っていました。しかし、実際に読んではいませんでした。そこで「できるPy」の依頼を受けたときに購入してどのような内容かを確認しました。

「退屈なことはPythonにやらせよう」は616ページあります。これは Python 入門と実践的なプログラミングの2つの題材が1冊になっているからです。これから初めてプログラミングを学ぶ人にとっては入門から始めてステップアップしながら1冊でたくさんのことを学べます。インタラクティブシェルを使って実際に1行ずつコードを入力・実行しながらその結果を確認して理解していくといったスタイルで書かれています。実際に手を動かしながら学べることから初学者向けとしてとてもよい本だと私は思います。

書店巡り

執筆はそれなりに苦労したにも関わらず、もしくは苦労した甲斐もあって実際に書籍としてリアルな本を手に取ったとき、なんとなく嬉しくなって舞い上がってしまいました。コアタイムが過ぎたら退勤して、近くの書店巡りをして実際に置かれているか調べに行きました。

f:id:t2y-1979:20190523160422j:plain:w1024
丸善ジュンク堂さんの棚

f:id:t2y-1979:20190523162648j:plain:w1024
紀伊国屋さんの棚

私が巡った書店ではどちらも本書の師匠である「退屈なことはPythonにやらせよう」の隣に並べられていました。お客さんにとってどちらが良いかを比較して選びやすい最適な棚配置だと私は思います。

「できるPy」と「退屈なことはPythonにやらせよう」のどちらを選べばよいですか?

と質問をしたくなるでしょう。

もし質問者がこれからプログラミングを学び始めようという方であれば、私は迷わず「退屈なことはPythonにやらせよう」をお勧めします。

「退屈なことはPythonにやらせよう」は素晴らしい内容ですし、扱っている題材も多くすべての章節を読まなくても読者の興味がある分野をみつけるときに「できるPy」では扱っていない題材をみつけることもできます。

じゃあ「できるPy」は発売時点でオワコン?

いえいえ。そんなことはありません。

プログラミングの勉強に限った話ではありませんが、勉強というのは結局のところ独学が基本です。もちろん勉強会へ行ってモチベーションをあげたり、セミナーに通って講師に指導を受けたり、友だちにわからないところを教えてもらったり、いろんな勉強のスタイルはあります。しかしながら、ある程度のスキルを身に着けるには独学でたくさんの時間をかけて学ぶ必要があります。

書籍というのは最も身近で安価に独学を助ける教材の1つです。たくさんの書籍がある理由の1つとして、人それぞれに趣味趣向があり、本人が読みやすい分かりやすいと思う書籍の内容、構成、分量、体裁は異なると私は考えています。本書は熱意のある編集者さんが体裁を整えて校正してくれたおかげで初学者にとってかなり親切な内容になっていると私は思います。いくら詳細に説明されていても読まない本より、基本的なことしか書いていなかったとしても読む本の方が独学の助けになります。

大事なことは自分にとって気に入った本を選ぶこと、独学を続けられそうな本を選ぶことだと私は思います。その視点から「できるPy」が「退屈なことはPythonにやらせよう」よりも勝るかもしれない点をいくつかあげます。

  • 書籍の値段
  • コンテンツの見た目
  • 技術的詳細よりも動くコード

書籍の値段

とてもわかりやすい比較指標です。

  • 「退屈なことはPythonにやらせよう」: 3,996 円 (税込)
  • 「できるPy」: 2,484 円 (税込)

単純な値段の比較で「退屈なことはPythonにやらせよう」が割高であると私は思いません。こちらは Python 入門についても丁寧に説明されているので分量が多くなっています。むしろ内容の充実度からすれば割安といえます。しかし、いまや数多くの Python 入門書が出版されていることから読者によっては他の書籍で Python 入門を終えていて、入門についての内容は不要という人もいるでしょう。

Python 入門が不要、且つ読者が読みたい題材を「できるPy」が扱っているのであれば、値段の安い方を選択するのもよいでしょう。

コンテンツの見た目

私は本を選ぶときに見た目を気にする方です。漫画も好きでよく読む方なのですが、絵柄の雰囲気が好みかどうかがその連載を読み続けるかどうか、時間をかけて読むかどうかに大きく影響します。そのため、自分にとって見やすいかどうかをぱらぱらページをめくりながら判断します。

もちろん知りたい内容がその本しか扱っていないのであればその本を購入するしかありません。しかし、「できるPy」のような初学者向けの本は上位互換として「退屈なことはPythonにやらせよう」がありますし、私が知らない同コンセプトの本もたくさんあるでしょう。読者が見やすい、読みやすいと感じる本を選ぶとよいと思います。

参考までにそれぞれの本の見た目を紹介します。

f:id:t2y-1979:20190525042314p:plain:w1024
退屈なことは Python にやらせよう -14 章 CSV ファイルとJSON データ-

f:id:t2y-1979:20190525042318p:plain:w1024
できるPy -029 CSV ファイルを読み込む-

余談ですが、CSV ファイルを扱うのに「退屈なことはPythonにやらせよう」は標準ライブラリの csv モジュールを、「できるPy」ではサードパーティライブラリの pandas を紹介しています。Python のインストールを Anaconda を使って行うとデフォルトで pandas もインストールされます。本書はビジネスパーソン向けということもあり、標準ライブラリよりも便利であれば、サードパーティライブラリを優先して紹介するようにしています。

また執筆はリブロワークスさんの MDBP という Atom プラグインを使いました。Markdown で原稿を書いて CSS でスタイル設定して Atom で実際の書籍のデザインに近い見た目で確認しながら行いました。とてもよくできたプラグインで公開されています。興味のある方は Atom と MDBP プラグインをインストールして試してみるとよいでしょう。

libroworks.co.jp

技術的詳細よりも動くコード

本書を執筆するにあたり、マーケティング業務に携わっている同僚にヒアリングしていたときにこんな話を聞きました。

プログラミング言語の文法がどうこうとか、仕様が云々とか、そういうのは全く興味がありません。サンプルコードの一部の処理やパラメーターを直せばよいというのさえわかれば、適当に変更して実行して、それで目的が達成できればよいです。

プログラマーにはない感覚です。目的が明確なので手段はどうでもよく、目的を達成するコードが動けばそれで満足だというのです。本書を執筆する過程でこのことは私の中で葛藤と逡巡をもたらしました。確かに勘のよい人であれば Python のコードを読んでいるうちに規則性や要点をなんとなく掴んでパラメーターや必要な箇所のみを書き換えてプログラミングできるかもしれません。プログラミングに慣れるという最初の取っ掛かりとしてはそれでよい場合もあるでしょう。

本書は実務で使えるサンプルコードを提供するという目的がありました。サンプルコードはサンプルコードでしかなく、実務というのはそれぞれの業務に特化した個別の事情や要件があり、どういう仕組みや理屈で動いているかをわからずに書き換えて通用するかという懸念があります。しかし、ちゃんと解説したところで詳細に興味がなくて読まない人たちもいるかもしれないというので困ってしまいました。どこまで詳細を説明するか、あるいは説明しないかを考えて悩みながら書いたのが本書になります。

例えば、本書の中で意図的にサンプルコードの詳細説明を省いたのが Chapter 8 の「050 PDFからテキスト抽出」の項目です。余談ですが、本書では PDF からのテキスト抽出に pdfminer.six · PyPI というライブラリを使っています。一方で「退屈なことはPythonにやらせよう」では PyPDF2 · PyPI というライブラリを使っていて異なる点の1つです。これは私の手元にあった PDF ファイルをいくつか PyPDF2 でテキスト抽出したところ、日本語の PDF ファイルのテキスト抽出ができませんでした。pdfminer.six は正常にテキスト抽出できたのでそちらを採用しました。pdfminer.six は開発者が日本人なのでテストデータとして日本語の PDF ファイルも使って検証しながら開発されたのだと推測します。

閑話休題。私の知る限り、pdfminer.six についてのドキュメントは次になります。

ドキュメントをみる限り、pdfminer.six のモジュール構造は PDF のデータ構造に大きく影響を受けているため、複数のモジュールを組み合わせて PDF からテキスト抽出する仕組みとなっています。そのため、このモジュールはどういった機能をもっているかを解説するには PDF のデータ構造について言及する必要があります。PDF ファイルからテキスト抽出するという目的に対して、PDF のデータ構造の詳細に踏み込むのは難し過ぎると私は思いました。そこで pdfminer.six のモジュール構造の説明は行わずにサンプルコードの使い方のみを説明しました。

逆の例として概要だけでも説明した章もあります。Chapter 5 の 「021 ZIPファイルに含まれるファイル名を文字化けさせずに表示する」で文字化けの概要を説明しています。もしかしたら読者層のビジネスパーソンな方々には全く興味のない話かもしれません。しかし、直接的に役に立たなくても文字化けが発生する仕組みがわかれば、なにかの機会に知識として役立つこともあるのでは?と考えてできるだけ簡潔に説明しました。

本書では実務で役立つサンプルコードを提供しつつ、その技術的詳細は最小限しか説明しないという、プログラマー視点からみるともやっとする微妙なバランスで書いています。そのため、本書で提供しているサンプルコードが読者のやりたい自動化処理に近ければ近いほどやりたいことを達成する労力を削減しやすいとも言えます。

まとめ

出版を契機に久しぶりに書店へ行ってたくさんの Python 本が置かれている棚をみました。私は10年前ぐらいから Python を学び始めました。当時と比べて、たくさんの入門本、データ分析や機械学習に関連した Python の本が敷き詰められていて驚くべき状況です。

数多ある入門本の末席の1つとして、本書をきっかけにプログラミングに慣れ親しむ人が増えて、世の中の業務のいくらかが自動化されて効率化されて誰かの役に立てば幸いです。

本書の紹介記事

本書を紹介してくれた方々のブログの記事をまとめます。

shinyorke.hatenablog.com

イベント登壇

medium.com

リファレンス

出版にあたり、共著者やアドバイスしていただいた方々やレビューをしていただいた方々の記事も紹介します。関係者の方々のおかげで出版できたことに感謝します。

xaro.hatenablog.jp

rokujyouhitoma.hatenablog.com

できる 仕事がはかどるPython自動処理 全部入り。 (「できる全部入り。」シリーズ)

できる 仕事がはかどるPython自動処理 全部入り。 (「できる全部入り。」シリーズ)

これからはじめる SQL 入門

レビューに参加した経緯で 技術評論社 さんから献本していただきました。ありがとうございます!

SQL とはなにか

本書は「データベースを操作するための言語」として、RDBMS とその実行環境として PostgreSQL を使って SQL 入門を行います。私自身、これまでおもに RDBMS を使ったシステム開発に携わってきたことから「データベース」と聞くと RDBMS を真っ先にイメージしてしまいます。本書ではローカル環境にインストールされたデータベースに対して実際に SQL を実行して、その結果を確認するといったようにインタラクティブに操作しながら学習を進めていきます。

一方で「Chapter 1 データベースと SQL」をレビューしていて私自身の「データベース」の背景についての誤解に気付いたり、SQL とはなにかと考えるよい機会となりました。もちろん本書は入門者向けに簡潔に説明されているので、データベースそのものやそのモデルの背景や歴史的経緯などについては説明されていませんし、これから SQL を学ぶ人たちが最初にそういったことを気にする必要もありません。

SQL は1980年代に生まれた技術であるそうです。古くからある技術がいまもなお使われ続けているということから多くの歴史的経緯や変遷を辿っていることが伺えます。いまも SQL が使われる分野は拡大されていて、仕様も拡張され続けています。直近で拡張された規格を3つあげると、2008年、2011年、2016年になるそうです。

例えば SQL:2016 を調べてみると、json を扱う機能であったり、Row Pattern Recognition という正規表現を使って特定の行グループを絞り込む (ログのような時系列なデータからグループ分割したものに条件指定して取り出す?) ための機能であったりが追加されています。その時代で求められる機能や要件を取り込みながら SQL は進化しています。「SQL とはなにか」という問いへの答えも、その時代でよく使われている用途に応じて変わっていくように私は思います。

本章の最後に「クラウドコンピューティングとデータベース」というコラムがあります。そのコラムではクラウド環境で利用される RDBMS の紹介に加え、DWH (データウェアハウス) のプロダクトの問い合わせにも SQL のサブセットが使えることが紹介されています。DWH も SQL を使うプロダクトの1つとして大きな領域です。ここでさらに wikipedia の Database#Examples をみると、データベースを分類する方法として3つの方法があると記載されています。

データベースを分類する方法として、1つ目は書誌、文書、統計、マルチメディアといったその内容の種類から、2つ目は会計、音楽、映画、銀行、製造業、保険といったアプリケーションの分野から、3つ目はデータベース構造やインターフェースの種類といった技術的な側面から分類されます。

これらの分類方法から wikipedia では DWH 以外にも様々なデータベースが紹介されています。記載されているもののうち、私が見聞きしたことのあるものだけを取り上げてみても以下のようなものがあります。

  • インメモリデータベース
  • クラウドデータベース
  • 分散データベース
  • ドキュメント指向データベース
  • 組込みデータベース
  • グラフデータベース
  • ナレッジベース

もちろん、関係モデルをデータ構造として扱うデータベースであれば、このような分類の違いをあまり意識することはないかもしれませんし、全く独自のクエリ言語を提供しているものもあるかもしれません。ついつい身近に使っているものだけをデータベースであるかのように錯覚してしまいがちですが、データベースには多くの種類があります。そして、その多くで SQL (またはそのサブセット) を使ってデータを操作できることは、ライブラリの再利用性、システムの相互運用性、学習コストの削減など、多くのメリットがあります。

今後も新しいデータベースが現れてくるでしょう。しかし、そのプロダクトが SQL (またはそのサブセット) を提供する限り、その分類に関係なくそのデータの操作ができます。SQL を使えるということは、IT エンジニアだけではなく、業務においてデータに関わるすべての職種、営業であったりマーケティングであったり、カスタマーサポートであったり、それ以外の多くの職種の人にとって重要なスキルとなるでしょう。

SQL を手打ちして慣れる

本書をレビューしていて過去のことを思い出しました。昔、私は SIer である基幹システムのヘルプデスクのような業務に携わっていました。お客さんから基幹システムのデータや処理についての問い合わせがあったときに調査して回答するといったような業務です。

基幹システムのデータベースにはお客さんの PC からもアクセスできる状態でした。データを直接みたいときにお客さんは Microsoft Access を使ってデータを確認していました。特定テーブルのデータをみる分にはそれで十分であったかもしれませんが、様々な調査のために複数テーブルのデータを結合し、ある条件でデータを絞り込みたいときなど、私宛に連絡がきて、私が SQL を使って該当データを調査して回答するといったことが日常でした。

Chapter 3の最後に「SQL を身に付けるには」というコラムがあります。

筆者の経験を踏まえて、1つアドバイスがあります。それは コピー&ペーストに頼らず、自分の手でタイプして体になじませる というものです。

このコラムに書かれている著者の経験に私は全く同意するところです。私自身も SQL に慣れるきっかけになったのが、日常的にお客さんから問い合わせを受けて、必要なデータを取得する SQL を手入力して調べたりしていました。

そして、SQL に慣れてきたときに運用工数を削減することを目的に、お客さんにも SQL を覚えてもらおうとしていた時期もありました。当時やり取りしていた情報システム部の担当者も自身のスキルアップを目的に SQL を学習したいと仰っていました。そこで問い合わせの回答をするときにそのデータを調査したときの SQL も添付して回答していました。そんなことを半年ぐらい行っていたのですが、残念ながらお客さんの方が SQL はやはりわからないと学習を断念してしまいました。

いま思い返すと、そのときに本書があったらまた違った結果になっていたのではないかと悔しく思います。まさに私がお客さんに提供していたのはコピー&ペーストできる SQL であって、お客さんが自分で手打ちして SQL を覚えるための仕掛けとして不十分であったことが本書を読んでいて実感した次第です。これから SQL を学習される方は、本書を読み進めながらコピー&ペーストせずに手打ちしながら SQL に慣れていくのを実践してみてください。

本文とコラムとのバランス

冒頭の「はじめ」のところで以下のように書かれています。

本書は、著者が初心に戻り「自分が SQL を学び始めたときにこのような解説書があればよかった」と思える一冊に仕上げようという思いで筆を執ったものです。

著者が IT エンジニアであるため、システム開発する上で迷うところやつまづきそうな落とし穴、有用な情報を「コラム」として所々で補足しています。SQL を学ぶという視点からは確かに副次的な情報であるため、そういった情報は本文に含めずにコラムとしてうまくバランスをとっているように思います。というのは、本書の読者は IT エンジニアだけではないと想定しているのだと思います。私がレビューしていて、こういった情報もあった方が良いのではないかと指摘したこと・しようと思ったことの大半がコラムで簡潔にまとめられているので親切な入門書になっていると思います。

コラムの目次がないのはもったいないと思ったので以下にまとめてみました。

Chapter 1 データベースとSQL

Chapter 2 PostgreSQL環境の準備

  • Column: 環境構築やツールに関する補足情報 ・・・ 42

Chapter 3 データの取得と絞り込み(SELECT)

  • Column: ORDER BY 句を省略した場合の並び順 ・・・ 57
  • Column: OFFSET 句の代替 ・・・ 82
  • Column: SQL を身に付けるには・・・ 84

Chapter 4 データの作成・変更(INSERT,UPDATE,DELETE)

  • Column: CRUDSQL ・・・ 102

Chapter 5 データ型

  • Column: 文字型をどう使い分けるか? ・・・ 114
  • Column: 符号なし整数を扱うデータ型は? ・・・ 118
  • Column: シーケンスの重複を自動で防ぐには? ・・・ 125
  • Column: もっと複雑な配列も扱える ・・・ 135
  • Column: そのほかのデータ型 ・・・ 138
  • Column: JSON 型の使いどころ ・・・ 143

Chapter 8 テーブルの結合

  • Column: AS も省略できる ・・・ 205

Chapter 9 サブクエリ

  • Column: IN と EXISTS の違い、JOIN への書き換え ・・・ 240

Chapter 10 一歩進んだ SQL

  • Column: 全文検索システム ・・・ 251
  • Column: WHERE 句で関数や演算子を使う際の注意 ・・・ 252
  • Column: WITH 句を使った SELECT 文 ・・・ 263
  • Column: ほかの RDBMS での UPSERT ・・・ 266
  • Column: オートコミット ・・・ 273

Chapter 11 データベースとテーブルの操作

  • Column: 複数の制約を組み合わせる ・・・ 287
  • Column: ほかの RDBMS では列の場所を指定できる? ・・・ 287
  • Column: VIEW の変更 ・・・ 314
  • Column: データベースと日本語 ・・・ 315

まとめ

本書は SQL を段階的に学んでいく上で丁寧な解説と構成になっています。そのため、どちらかと言えばシステム開発に直接関わらない人向けにとってよい入門になると思います。冒頭でも述べた通り、データベースの重要性や SQL の応用範囲は広がる一方です。本書がデータを扱うすべての職種の人にとって SQL を学ぶきっかけになればと思います。

これからはじめる SQL入門

これからはじめる SQL入門

達人プログラマーの新装版がでたので読み直してみた

オーム社 さんから献本して頂きました。ありがとうございます!

原著は1999年10月20日に出版されたそうです。このブログ記事を書いているのが2016年11月なので17年前に書かれたことになります。元の出版社であるピアソンエデュケーション社が日本から撤退したことによりオーム社さんに移管され、その機会に翻訳も全面的に見直されたようです。

本書を読む動機付け

変化の速い IT 業界において17年前に書かれた本をいま読む価値があるのか?この問いに答えるのは難しいです。

開発プロジェクトという日々の業務では、様々な要件や移り変わる状況の中で何かしら制約がありつつも判断を下さなければなりません。それはアーキテクチャの策定であったり、開発方法論の実践だったり、個々の技術の選定だったりします。そこで判断を下し、そのときの判断が正しかったのかどうか、本当の意味でその正否はその後の歴史でしか分かりません。さらに何をもって正否と判断するのか。この正否の判断自体も多様な価値観で行われるものですが、達人プログラマーの原題である The Pragmatic ProgrammerPragmatic (実践的) という意味を借りて、広く浸透している考え方やうまく運用がまわっている仕組みをここでは正しいとします。その考え方が本当に広く浸透しているのか、その仕組みが多くの現場で使われているのか、それを私が保証することはできませんが、私の周りで見聞きする分にはそうみえるということで話を進めていきます。

閑話休題。本書を読むことで17年前に書かれた考え方や仕組みが 実践的に 正しかったのかどうかの一端を知ることができます。ともすれば、IT 業界というのは新しい技術や方法論が毎年たくさん出てきて、生き残るものもあれば消えていくものもまた多いです。そんな業界で17年も生き残っているものがあるとしたら、それは普遍的なものだと言ってしまっても過言ではないかもしれません。目新しいものに注意を取られがちな日常で何が本質かを考えたときにその基礎を教えてくれる、歴史を経た 達人プログラマー は単にプラクティスをまとめた本ではなくなっているように私は思います。

ある程度、業務でプログラマー経験のある方は私のような読み方もできますが、一方で経験の少ない若い方にとってはどうでしょうか。もちろん若い方へもお勧めしますが、本書の中で特定技術を例として紹介されているものの中には、いまは廃れてしまって現状にそぐわないものもあります。そのため、若い方が聞いたことのない特定技術が出てきたときは、その技術については自分で調べ直してみることが必要になります。訳注で補足をしている箇所もいくつかあるのであわせて確認してみてください。

達人プログラマーの所感

私が印象に残った節についていくつか抜粋しながら簡単に所感を書いていきます。

4 十分によいソフトウェア

この節ではソフトウェアのリリースをどのタイミングで行うかといった考え方を書いています。内容自体はプロジェクトマネージャーやプロダクトマネージャー向けに書かれているものですが、私は読んでいて、一般の開発者がいつプルリクエスト (以下PR) を送るかというタイミングを考えるときに似ているように思いました。

コードレビューをするのが当たり前のワークフローになりつつある昨今、どのタイミングで PR を送るか悩む人もいると思います。私は自分の中で8割ぐらいの品質になったら気軽に PR を送る方です。言わば、いくつかツッコミ所を残した状態で PR を送っています。その理由は次になります。

  • その PR の課題に対する解決策として設計や考え方があっているかどうかを判断してもらう
  • 全体からすると些細な内容でどう対応するかを自分の中でも迷いがあるので意見がほしい
  • 自分が書いたコードの意図が他人に伝わるかどうかをみてみる

そしてレビューしてもらって設計や考え方があっていないのであれば、やはり気軽に PR を取りやめて再設計します。どんなに時間をかけて品質をあげても他人の視点をもつことはできません。もちろん自分の中ではこの設計方針がベストだと考えて PR を送るわけですが、それまで自分が考えていなかった懸念や概念を他人から与えられることによって、他のやり方が妥当だと思うこともあります。

せっかく書いたコードを捨てるというのは悔しい行為だと思います。時間をかければかけるほど、サンクコストも気になってしまいます。時間 (コスト) のかかる機能開発だと進捗を小まめにレビューしてもらって手戻りを少なくする工夫をすると良いと思います。

7 二重化の過ち

いわゆる DRY原則 を紹介しながら、いろんな状況で二重化が起きることを説明しています。システム開発をしていて最も身近な問題の1つと言っても良いかもしれません。

プログラミングを始めた人にとって、おそらく初期段階でそこそこの規模のアプリケーションを実装していると実感すると思います。引き継いだ既存のアプリケーションの品質がよくないとそういった重複コードに悩むこともあります。

原則はあくまで原則でしかなく、結局のところその場その状況において何が最善であるかを選択する必要がでてきます。メリット/デメリットを考慮した上でやむを得ず二重化するという判断も現実にはあるでしょうが、二重化には多くの弊害があるという事実を知っておくことが重要です。そして、そうならないようにどうすれば良いかを考えていくことも重要です。そういう考え方をしているうちに、言語機能、設計手法や開発方法論で解決しようとしていることへの理解にもつながっていくように私は思います。

8 直交性

ときどき聞く言葉なのに私はちゃんと定義を把握していなかったので再学習しました。

「直交性」とは幾何学の分野から拝借してきた用語です。(中略)。この用語はコンピューティングの分野では、ある種の独立性、あるいは分離性を表しています。2つ以上のものごとで、片方を変更しても他方に影響を与えない場合、それらは直交していると呼ぶわけです。

直交性は DRY の原則とも密接に関係しています。またこの節では設計、ツール、コーディング、テスト、ドキュメントにおいても直交性の概念が適用できると紹介しています。

優れたフレームワークやライブラリ、良いプラクティスが共有されやすい昨今だと、直交性は当たり前過ぎてあまり意識することはないかもしれません。そういった背景にある概念を学ぶ良い機会にも思いました。

12 専用の言語

いまの言葉にすると ドメイン固有言語 (以下DSL) に相当すると思います。Tips としては以下のように書かれています。

問題領域に近いところでプログラミングを行うこと

この概念自体は適切だと思いますが、その事例の1つとしてミニ言語を実装する事例が紹介されています。またそれが必要な根拠として sendmail の設定は複雑なので DSL により制御を容易にする例を紹介しています。

達人プログラマーに書かれているほとんどの内容は、小さい開発プロジェクトにも大きい開発プロジェクトにも両方適用できるように書かれていますが、DSL に関して私は慎重派なので反対の立場にたってその理由を書いてみます。

もちろん巨大で複雑なプロジェクトや十分に成熟したアプリケーションに対して DSL が大きな価値を提供する場面があることは私も同意します。あえて反論しようと思ったのは DSL を開発するデメリットもあるからです。

  • 開発者にとって DSL の開発・保守コストがかかる
  • ユーザーにとって DSL の学習コストがかかる
  • ユーザーにとって DSL で書かれた機能や設定の保守コストがかかる
  • アプリケーション本体の機能と DSL が提供する機能の間にズレが生じる可能性がある
  • アプリケーション本体と DSL の依存関係を管理する必要がある

ざっと思いついたものをあげてみました。自分が取り組んでいる開発プロジェクトでこれらのコストを負担しても DSL を使うメリットがある場合は取り組んでも良いでしょう。逆にこれらのコストを考えずに安易に DSL を使うと将来の技術的負債となることもあると思います。

14 プレインテキストの威力

シンプル且つ意味深なように思えてなぜか印象に残りました。

知識はプレインテキストに保存すること

テキストの利点として以下をあげています。

  • 透明性が保証される
  • さまざまな活用ができる
  • テストが容易になる

いまどきの利点をさらにあげるとバージョン管理システムで差分管理しやすいという点も追加したいです。

これはこれで言っていることは正しいのですが、言わばテキストなら後から何とでもできるということでしかありません。もし特定用途に使いたいとしたらデータを正規化して扱いたくなるので、テキストデータは逆に曖昧で扱いにくいものです。例えば、HTTP/2 でバイナリープロトコルを採用した理由として、解析が容易でエラーチェックが厳密である利点があげられています。

18 デバッグ

私はこの節が好きです。残念ながらデバッグの手法は昔と比べてほとんど進歩がないように思います。大きく分けると以下の2つでしょう。

もちろん言語処理系の型システムが強力になったり、ツール/ライブラリが拡張されてより便利になったりはしています。しかし、エラーが発生して人間がソースコードを読みながら解析して原因を追求していくという行為自体はほとんど変わっていません。この節ではそのための心構えや戦略が丁寧に説かれています。

1つ私も過去にやっていた実践的な手法を紹介します。

問題の原因を探し出すための非常に簡単で効果的なテクニックとして、「誰かに説明する」という手法があります。

これはデバッグに限らず、コードレビューをレビューツール上だけでなく、レビューアに対面で説明するときにも有効です。説明しているうちに自分でもっと良い方法を思いついたりすることもあります。おそらく人間の思考として、ものごとを多面的にみる上でアウトプットの方法を変える手法が強力なんだと思います。

21 契約による設計

この節はどうなんでしょうね?あらかじめ要件や仕様を厳密にしやすい業務系ではこういった設計が定着しているのでしょうか?私は経験がなくて実践的にこの手法が使われているのかどうか知りません。

Web 業界ではまだまだここまで厳格な設計手法は定着していないように私は思います。また別の節にある表明プログラミングもそうですが、厳密さを保証するためのオーバーヘッド (実行効率や保守性など) もかかることから敬遠されがちなところもあると思います。

そう思ってはいるものの、最近契約による設計に関する記事をみかけたので以下を紹介しておきます。

28 時間的な結合

マルチスレッドを用いた並列処理について説明されています。さすがにこの節の内容や例は古くなってしまっているように感じます。非同期/並行処理 *1 は、プログラミング、システム設計、いろんな状況で本質的に難しい課題です。

この節ではワークフロー、アーキテクチャ、設計、インターフェースについて説明されていますが、内容がいまどきの Web 開発の問題とはややあっていないかもしれません。もちろん本書は Web 業界向けに書かれたものではないと思いますが、それでも昨今のクラウド化や開発方法論の変化との乖離により違和感があるのは仕方ないように思います。

1つだけ補足しておくと、昨今はそれぞれのプログラミング言語が非同期/並行処理をサポートする機能を提供していたりします。例えば、Python では asyncio というライブラリが標準で提供されています。そのライブラリはプログラマーが陥りがちな落とし穴を回避してくれます。そのため、自分で一から考えて作り込むのではなく、その言語やライブラリが提供する機能や仕組みに沿って開発するのがいまどきのプラクティスになるのではないかと思います。

31 偶発的プログラミング

本書を読みながらツイートしていて最も Impressions が高かったのがこの節でした。開発者が自分で実装しているコードをあまり理解せずに実装を進めてしまい、あるとき動かなくなってしまうときの背景や状況について説かれています。

いまはプログラミングを学ぶドキュメントがインターネット上にたくさんあっても、おそらくこの問題は昔よりも現在の方が起こりがちではないかと想像します。そして私自身も程度の違いはあれど実際にやっていると思います。誰かが作った優れたフレームワークやライブラリもこのことを助長します。

さらに何らかの問題や分からないことがあっても、大抵は stackoverflowqiita がその解決策として検索にヒットします。ほとんどの場合において、そこに書かれている内容を試せばうまくいくと思います。コードをそのままコピペする人もいるでしょう。それを繰り返した結果、簡単に偶発的プログラミングに陥ってしまいます。

以前ドワンゴの川上さんが仰っていた 膨大な数の二流のウェブエンジニア という言葉がずっと頭の中に残っています。

36 要求の落とし穴

この節も私は好きです。

要求は拾い集めるものではなく、掘り起こすものである

この言葉は的を射ています。要件定義はスキルの有無や頭の回転の速さに関係なく、その人の当事者意識の在り方に影響すると私は過去の経験則から考えています。つまり話を取りまとめて形式化するのが上手なことと、適切な要件を掘り起こすこととは違うということです。その当事者意識とはどうやって得られるのかの最たることも Tips に書かれています。

ユーザーの視点に立つには、ユーザーと働くこと

実際に業務でできるかと言うと難しい状況もあります。開発者がユーザーの気持ちを理解することが重要なのは誰しも経験から分かってくるように思います。ドッグフードを食べるとも言われたりしますが、可能であれば自分が開発しているアプリケーションやシステムを自分で積極的に使うことが最初の一歩になるはずです。

38 準備ができるまでは

この節では自分の勘と経験で直感的におかしいと感じたら一旦立ち止まることの大事さについて書かれています。そして、そのときにプロトタイピングがその不安材料を洗い出すことに役立つともあります。

ちょっと精神的な話になるかもしれませんが、私は無意識に考えることを意識的に活用するときがあります。難しいバグに悩まされている最中、帰ってきて寝て起きたら手がかりを閃いたという経験がある人も多いと思います。

未経験のものごとに取り組んでいると心理的に不安に思ってしまうのは仕方ないことです。そのときは分からなくてもずっと考え続けていることで、あるとき閃くんじゃないかと楽観的に信じ続けることが良い方向に働くときもあります。勉強するときもこのことは役に立ちます。いま分からなくてもずっと勉強しているとあるとき分かるんじゃないかと諦めてしまわない根拠に使えます。

誰しも分からないという状態は辛いです。その分からないストレスを下げる工夫にもなるのではないかと私は思います。

読みながらそのとき思ったこと・考えたこと

本書を読みながらツイートした内容です。余談ですが、先の所感を紹介する節を選定するときに自分のツイート分析から多くの人が関心をもってそうなものも考慮しました。ハッシュタグをつけておけば良かったと後で後悔しました (´・ω・`)

リファレンス

新装版 達人プログラマー 職人から名匠への道

新装版 達人プログラマー 職人から名匠への道

*1:この節では並列と並行の詳細には触れないとあるので、ここでも並列と並行の違いについては触れません。私の感覚的なもので非同期と並行をセットで考えるのでそのように書いています

Python と型ヒント (Type Hints) と #pyconjp

先週末は PyCon JP 2015 に参加してきました。

どうでも良いことですが、たまたま会社がシルバースポンサーになっていましたが、参加そのものは個人でした。結果的には会場に会社ブースもあったため、そこでお手伝いもしつつの参加となりました。私以外にはどうでも良いことですね。

会社のブログにもイベント参加の所感を書いたので興味があればそちらもどうぞ。

型ヒントの発表

年明けから余裕があったので型ヒントの調査をしてきました。私自身、難しいことは分からないのですが、型システムに興味が出てきたところでいろんな言語の型システムをみてコードを書いたり、その特徴を調べたりするのがいまはおもしろいです。最近は Go 言語を主に書いていて型推論を伴う静的型付け言語の強力さを実感したりしています。

そして動的型付け言語に型ヒントを入れるという逆のアプローチもやはり興味深いです。Python では mypy が成功を収め、その型アノテーションの構文が PEP 484 で標準化されました。これまでも何度か mypy についての記事を書いてきました。細かいところは変わってしまっていますが、経緯や背景は変わっていないので興味のある方は以下も参考にしてください。

そして、これまで私が調べたことの集大成として PyCon JP 2015 で発表してきた次第です。

togetter はこちら。

聴講してくれたのは100人前後だと思うのですが、発表者と聴いている人たちとの距離感が近かったので私の中では発表しやすかったように思います。

発表直前、小山さん (@) が私の真前のスペースで

ここ地べたに座って聴いても良いっすか?

と声を掛けてくれて適当に「良いですよー」と答えながら、なんか少し緊張がほぐれて発表を開始しました。

何度か聴衆席に質問を投げかけながら進めました。Pythonのパラドックス を知らない人が大半だったりと世代が変わっているなぁと実感しました。発表の中で Python3 のパラドックスみたいな冗談も言っていますが、意図としては Python3 への移行を阻むものはほとんどないはずなので新しいものを作るときは Python3 を使おうよという呼びかけです。

移行が着実に進んでいるというの以下のアンケートなどから伺えます。

型ヒントについての詳細は PEP 484 型ヒントの翻訳 を眺めてもらうのが一番良いと思います。それなりの分量がありますが、興味のあるところから読み進めるのでも良いでしょう。サンプルコードも付いているので分かりやすいです。

型チェッカー

本節では発表のときにあまり触れなかった、型チェッカーとしての mypy を使ってみた私の所感を書きます。PEP 484 では型アノテーションの構文の標準化のみで型チェッカーは付属していません。そのため、依然として mypy は自分でインストールしなければなりません。

結論から先に書くと、型チェッカーとしての mypy はまだ実用レベルとは言えないです。github の mypy プロジェクトをみても250以上の issue が報告されており、期待する動作には至っていないようにみえます。

ちなみに mypy の PyPI 上のパッケージ名は mypy-lang というパッケージ名です。mypy という名前のパッケージが既に使われているためです。ちなみにこれは wsgi フレームワークだそうです。インストールするときには間違えないようにご注意を。

mypy の最新バージョンは 2015-04-05 に 0.2 というバージョンがリリースされています。この時点では PEP 484 のドラフト状態であり、そのときに決まっていた内容、おそらくは PyCon US 2015 で一定の合意を得た内容だったのではないかと推測します。

その後、PEP 484 が正式に認可されたのが 2015-05-22 です。

なぜか7月前後の master ブランチの開発は停滞していますが、その後8月頃からまた開発がアクティブになっています。それでも Python 3.5 と同じタイミングで 0.3 をリリースできてなく、また雰囲気的にも近々リリースするようにみえません。

github から mypy のソースをクローンしてきて、発表前にいくつかサンプルコードの型チェックなどを試したりしてみました。そのときにちょっと触って気付いたこと = うまく動かないところ = 既知の issue をいくつか見つけました。

やっぱり型チェッカーって大変なんだなぁというのが素朴な感想です。issue のページで label:pep484 でフィルターしても現時点で17個あります。mypy の 0.3 がリリースされるまでは型チェッカーは様子見といったところかもしれません。

今朝 git pull して動かそうとしたら bultins が見つからないというエラーになりました。

(mypy)$ mypy tutorial.py 
tutorial.py:1: error: Could not find builtins
...

パスの問題のようです。

いま mypy にコントリビュートするチャンスがたくさんありそうです。

型チェックは必要?

発表を聴いてくれていた同僚のデータサイエンティストに発表後どんな印象を受けましたか?と尋ねてみました。すると、やはり難しいと答えが返ってきました。ジェネリクスとか、これは Python なの?といった印象を受けたそうです。ジェネリクスの話をする際、会場で Java やったことがある人?と尋ねたら8割以上、手が挙がったので「ジェネリクスとは」みたいな話を省いてどんどん話を進めたのもあるかもしれません。

発表後の質疑応答においても、例えば 共変性と反変性 とか、Python はそういうことを考えずに簡単に使えて良いのに、、、といった質問もありました。私も説明が難しいからこの内容は発表から省いたのですが、確かに型ヒントをちゃんと書こうと思ったら分かっている人しか書けない、直感的に書ける類のものではないという意味で難しいです。

型チェックを誰が必要としているか?というと、その回答は学習コストやメンテナンスコストを払ってでも実行前に型チェックしたいかどうかの動機次第かなと思います。以下の清水川さん (@) の記事で Guido 自身も PyCharm や Google でも似たようなスタブファイルを作っていたから標準化することに意義があるんだと語っています。

私の経験からだと、実行前にエラーが知りたいケースは高い SLA が要求されるアプリ、または大規模なアプリだと思います。チーム開発で日々コードを書いてコミットしていると、他の人が何をやっているか分からないために認識の違いによるバグは常に入ってしまいます。

そういったバグを見つけるために動的型付け言語はテストをたくさん書くことで一定の品質を担保してきたわけですが (もちろん静的型付け言語でもテストは必要ですが)、その規模拡大に伴ってもうしんどくなってきたというのが現状ではないかと私は思います。アプリの規模が大きくなればなるほど、テストで品質を担保するのが難しくなります。

  • 全てのテストケースを網羅できない
  • テストのメンテナンスコストがかかる
  • テストの質が開発者のスキルに依存する

型チェックはテストなのか?と言うと議論はありそうですが、型レベルの操作において不整合がないことは、人間がプログラムを書く上で失敗しやすいミスを防いでくれます。

  • 人間はコードを書き間違える (typo)
  • 人間は全てのソースコードを把握してコードを書けない
  • 人間は時間が経つとそのソースコードを書いたときの経緯を忘れる

これらの失敗に対して型チェックは有効です。自分が全てを把握できていないコードベースにコードを追加していくとき、エラーを未然に防ぐことへの安心感をプログラマーは求めている気がします。

まとめ

型ヒントを扱う型チェッカーや IDE がどのぐらい普及するか、またはさらに便利な用法が出てくるか、まだまだこの先どうなるかは分かりません。とは言え、型ヒントそのものはあくまでオプションの位置付けなので悪い作用をもたらすことは何もないと思います。私ももう少し mypy が安定してきたら、それを使うテストツールなどを作ってみようと考えています。