Google Foobar Challenge を終えて

Google Foobar Challenge を知っていますか?

この記事に来た方は実際に発動したりどこかで見聞きしたかで調べているかと思います。僕はある土曜日の朝、突然 Google 検索の画面がおかしな動きをして初めてその存在を知りました。

Google Foobar Challenge とは

Google Foobar Challenge は Google がプログラミング関連の調べごとをしている人に「ちょっと遊ぼうよ」的な感じで発動するプログラミング問題(ゲーム?)のことです。

「宇宙空間に浮かぶラムダ司令官の悪の組織から、囚われの身になっているウサギちゃんたちを救う」という、どこのAIが考えたのか分からないストーリーを題材に、黒バックのコマンド入力画面の様なUIでプログラミングの問題を解いていきます。

途中まで解くと Google 社に自分の連絡先を送れたりもするので、本気で取り組む価値はあると思いますし、何より面白いです!好奇心旺盛な人にはたまらない時間になると思います。

そして僕はこの度めでたく全問クリア出来たので、記録として記事を書いてます。というか Foobar Challenge は全編英語というのもあって日本語の記事が全然見当たらなかったので書いてます。

挑戦するには?

URL はこれですが、ページに飛んだところで誰でも挑戦できるわけではなく、Google 検索をしている時に自然発生するのをただただ心待ちにするか、知り合いが頑張って取得した招待用リンクをもらうかの2つしかありません。

必要なスキル

必要なスキルとしては、まずプログラミングの基本的な知識と英語力。そして途中からはアルゴリズムの知識、そして終盤は数学の知識も必要になります。ちなみに言語は Java と Python が使えます。僕は Python で解いていきました。

もちろん初めから全部揃っていたら最高だとは思いますが、後述の通り回答に結構時間をかけられるので必要に応じて調べていくのでも問題ないと思います。

プログラミングの知識よりも発想力&想像力

プログラミングに関しては特に言語に精通している必要はないです。僕は Python 初心者で、そもそも今回 Google Foobar Challenge が発動した時も try-catch 文の書き方をググってたぐらいです。

それよりも問題を解決する方法を思いつく発想力や、色々な処理パターンを思い浮かべる想像力の方が大切だと思います。あとはそれを元に考えたロジックをコードに落とし込めれば大丈夫で、オブジェクト指向的な知識も全く必要ないです。

各レベルの内容

今後変更があるかもしれませんが、2021年1月時点ではレベル1〜5の全9問で構成されています。レベル1は本当に基本的な内容ですが、徐々に難易度が上がりレベル5はもう訳がわかりませんでした。問題自体は多分いくつかパターンがあると思うので、使うアルゴリズムの種類などは人によって変わると思います!

各レベルの主な内容を紹介します。

レベル1

まずは肩慣らしのような感じ。変数やループ等、プログラミングの基礎の基礎がわかっていれば大丈夫です。

  • 問題数:1 問
  • 制限時間:48 時間

こんな感じで進捗を確認できます。

レベル2

レベル 1 はプログラミング経験者なら誰でも解けますが、レベル 2 からはちゃんと頭を使う問題になります。このレベルをクリアすると友達に送る用のリンクを一つもらえます。

  • 問題数:2 問
  • 制限時間:各問題 168 時間(1 週間)
  • クリアすると:招待用リンクがもらえる(1 度目)

レベル3

経験者の書き込みをいくつか見ると、Google の採用面接で出されるコーディング問題はこの辺りのレベルだとのこと。このレベルをクリアすると Google に連絡先を送ることもできるので、ここまではがんばりたいですね!

  • 問題数:3 問
  • 制限時間:各問題 168 時間(1 週間)
  • クリアすると:Google に連絡先を送れる

迷路の最短距離の問題など、後になって考えてみればアルゴリズムの知識があればよかったなーと思いますが、想像力一本勝負でがんばりました。この辺りからは処理速度を気にしたプログラムを書かないと普通にタイムアウトでテストケースが Fail になります。

小休止(お勉強タイム)

このタイミングでアルゴリズムの知識を身に付けないとまずいと思い、下記の二冊をポチりました。

まず一つ目

アルゴリズム図鑑 絵で見てわかる26のアルゴリズム

こちらはプログラミング言語関係なくメジャーなアルゴリズムの概要をイラストでひたすら分かりやすく教えてくれます。「アルゴリズムとはそもそもなんぞや」だった僕にとっては最高の入り口でした。

そして二つ目

Pythonではじめるアルゴリズム入門 伝統的なアルゴリズムで学ぶ定石と計算量

こちらは、一冊目の「アルゴリズム図鑑」とほぼ同じアルゴリズムを、Python のコードではどう表現するのかを教えてくれます。最高です。

問題と問題の間はいくら時間を開けても良いので、心の準備ができるまで備えると良いと思います!

レベル4

ここからはいよいよ発想力だけではどうにもならなくなり、アルゴリズムが必須になります。そして流石の Google 先生。アルゴリズムを当てはめて終わりではなく、さらに一捻り二捻りする必要があります。

  • 問題数:2 問
  • 制限時間:各問題 360 時間(15 日間)
  • クリアすると:招待用のリンクがもらえる(2 度目)

1 問目は「せっかく学んだし」と思って幅優先探索を使ってみたんですけど処理に時間がかかりすぎたので結局別の方法に切り替えました。2 問目は最短経路を求めるベルマンフォード法を応用したイメージでした。

レベル5

いよいよ最終問題。そして流石の最終問題。もはやただの数学でした。

数学の知識はほぼゼロでしたが調べた内容を書くとするなら、バーンサイドの補題(Burnside’s Lemma)、ポリアの数え上げ問題(Polya’s Enumeration Theorem)、ユークリッドの互除法、順列と組み合わせ(Permutations & Combinations)、などなど。。。

  • 問題数:1 問
  • 制限時間:528時間(22 日間)

この記事(15.5 Applications of Pólya's Enumeration Formula)を読んでみたり、後述の動画をみたり。とりあえず何か掴めないか模索しました。

人によってはレベル4が一番難しいと感じる人もいるみたいですが、僕にとっては圧倒的にレベル5が一番難しかったです。途中ちょっと心が折れそうになりましたが、12日間かかってやっとクリア。

最終問題で参考にした動画

ポイント

  • 「verify solution」が数秒で終わらない場合はパフォーマンス的なところで Fail してる可能性があります。書いたコードの計算数をイメージすることが大事です。
  • 問題の細かいルールは読み取るのが難しいので、早めにコードを書いて「verify solution」でテストしながら察していくことが大事だと思います。
  • とはいえ問題はなるべく正確に理解する様注意した方がいいです(当然ですが)。自分の場合レベル 4 でコードをしばらく書いた後でどうにも上手くいかないのでよーく問題を読み直してみたら自分で理解していた条件と実際が異なることが分かり、ほぼ丸ごとロジックを考え直しました…。
  • ちっちゃいホワイトボードとかあると便利です。iPadとかでも良いのかな?その場で書いて消してを繰り返せるので。
  • 参考までに、僕の回答は大体数十行で一番多くても 200 行未満で済んだので(あくまで Python の場合)、もしもやたらと処理が多くなっている場合は考えすぎているかもしれません。

まとめ

コロナでのステイホーム中に突然始まった Google Foobar Challenge。思いの外夢中になってとてもエキサイティングな数週間になりました。初めは全てクリアできるとも思っていなかったので、最終的には自信を得られたことが一番良かったことかもしれません。

皆さんももし挑戦する機会があったら週末など出来るだけ時間を取れる期間を見つけて、思い切り没頭してみてください。きっと素敵なおうち時間になると思います。

import MySQLdb で実際にクエリを実行できるか確認する

mysqlclient をインストールしたので、実際にクエリを実行できるか簡単に確認します。

今回は WordPress で自動作成されたテーブルで、現在公開されている記事のタイトルを select しました。

% python3
Python 3.9.0 (default, Jan  3 2021, 10:29:59) 
[GCC 4.2.1 20070831 patched [FreeBSD]] on freebsd9
Type "help", "copyright", "credits" or "license" for more information.

>>> import MySQLdb
>>> conn = MySQLdb.connect(host='mysqlXXX.db.sakura.ne.jp', db='abcabc_notemite',user='abcabc',passwd='xxxxxxxxxxxx',charset='utf8mb4')
>>> c = conn.cursor()
>>> c.execute('select post_title from nm_posts where post_status = "publish"')
20
>>> c.fetchall()
(('サンプルページ',), ('【Wordpress】ショートコードを別ファイル管理でリスク低減',), ('【WordPress】ショートコードの表示・非表示を一発で切り替えたい',), ('【ターミナル】Mac のログインシェルを zsh に変える',), ('【Python】Macbook に Python3 をインストール',), ('【Python】「pip install requests」でエラー「pip3 install requests」で成功',), ('【Python】Mac に Beautifulsoup4 をインストール',), ('Homebrew を Macbook Pro へインストール',), ('Homebrew を使って Macbook に Wget をインストール',), ('【Wordpress】確かに「--」と書いたのに「–」と表示される件',), ('【8ステップでがんばる】さくらレンタルサーバーでWordPressサイト立ち上げ',), ('【ターミナル】さくらのレンタルサーバーにSSHでログインする方法',), ('さくらレンタルサーバに Python3 をインストールする方法',), ('【Python】さくらレンタルサーバーに requests モジュールをインストール',), ('【Python】Mac に MySQL モジュールをインストールする方法',), ('【2020年10月〜12月】YouTube 急上昇入りランキング',), ('さくらレンタルサーバーに libffi をインストールする',), ('【2020年1月〜】YouTube 急上昇入りランキング',), ('さくらレンタルサーバーで Python3 を再インストール',), ('【Python3】mysqlclient のために _ctypes と格闘した記録',))
>>> 

execute() の実行結果(上記「20」の部分)はクエリの結果として返されたレコード数を表示しています。fetchall() を実行しないとクエリの実行結果は見れないんですね。

さくらレンタルサーバーで Python3 を再インストール

一度 Python3 をインストールしたのですが、mysqlclient をインストールするために Python3 を入れ直す必要があったのでそのステップを書きます。

アンインストール(仮)

まずは既存の Python3 を一旦アンインストールします。インストール先のフォルダを削除する必要があると思いますが、削除は怖いので一旦フォルダ名だけ変えます。

下記の通りパスが通っている状態です。

% which python3
/home/abcabc/local/python/bin/python3
% which pip3
/home/abcabc/local/python/bin/pip3

フォルダ名が変わったため、パスが通っていない状態になりました。

% which python3
python3: Command not found.
% which pip3
pip3: Command not found.

ダウンロード〜インストール

ここから先は基本的に下記の記事でやった内容をなぞるだけですが、今回 ./configure 文を変えました。

ダウンロード

% mkdir -p ~/work/python3
% cd ~/work/python3
% wget --no-check-certificate https://www.python.org/ftp/python/3.9.0/Python-3.9.0.tgz

解凍

% tar zxf Python-3.9.0.tgz

インストール

% cd ./Python-3.9.0
% ./configure --prefix=$HOME/local/python/ --with-system-ffi LDFLAGS="-L $HOME/local/lib/" CPPFLAGS="-I $HOME/local/include/"
%  make
%  make install

ここまで完了したら、以前通したパスが生きているので下記の通り which コマンドで既に確認できる状態です。

% which python3
/home/abcabc/local/python/bin/python3
% which pip3
/home/abcabc/local/python/bin/pip3

使い終わったフォルダとファイルの削除

最後にファイルダウンロード用に作ったフォルダと、既存の Python3 が入っていたフォルダ(の名前を変えたもの)を削除します。

% rm -r ~/work/python3
% rm -r ~/local/python_20210103

ついでに

環境変数の追加

初めて Python3 をインストールした時はスルーしていましたが、どうやら下記を .cshrc に追記した方が良いみたいなのでこのタイミングで追記しておきます。

setenv  PYTHON $HOME/local/python/lib
setenv  PYTHONPATH $HOME/local/python/lib/python3.9/site-packages

requests モジュールをインストール

元々インストールしてあった requests モジュールを再度インストールします。

% pip3 install requests

【Python3】mysqlclient のために _ctypes と格闘した記録

経緯

さくらのレンタルサーバー上で MySQL のデータベースを使えるので、それを Python で操作したいと思ったのが始まりです。mysqlclient を使えば良いらしかったので「pip3 install mysqlclient」を実行するも、エラーが出て成功しない。なんとかインストールを終えるまでの過程が文系の私には?だいぶややこしかったのでその記録を書き留めます。

  1. 問題発生1(No module named '_ctypes')
  2. 調査と原因1(libffi が無い)
  3. libffi をインストール(sudo は使えない)
  4. 問題発生2(INFO: Could not locate ffi libs and/or headers)
  5. 調査と原因2(./configure 文の修正)
  6. 解決(mysqlclient インストール成功)

問題発生1(No module named '_ctypes')

上記の通り「pip3 install mysqlclient」を実行したところ、下記のエラーが出てインストールが失敗しました。

ModuleNotFoundError: No module named '_ctypes'

直訳すると「_ctypes モジュールがありません」

_ctypes モジュールとはなんぞや。そしてそれはどこにあるのでしょうか。。。

調査と原因1(libffi が無い)

取り敢えず知識ゼロから出来ることは、情報の海に身を投げてなんとなくわかるまで溺れること。。。調べた結果断片的ですが自分の理解できる範囲で下記の情報が得られました。

  • Python の _ctypes は C 言語で書かれたライブラリを Python から利用するためのモジュールであり、libffiに依存している。
  • ソースからPythonをビルドする際、libffiが見つからない場合は _ctypes のビルドはスキップされる。
  • つまり、libffi がない状態で Python をインストールしたため、_ctypes のビルドがされていなかった。
  • _ctypes がビルドされていない Python から _ctypes を利用しようとすると、当該エラー(ModuleNotFoundError: No module named '_ctypes')が発生する。
  • 当該エラーを解消するには、libffi をインストールした上で Python を再ビルド・再インストールする必要がある。

libffi をインストール(sudo は使えない)

「sudo apt-get install -y libffi-dev」というコマンドが出てきましたが、さくらのレンタルサーバー(スタンダード)では管理者権限が与えられていないので sudo が使えません。

% sudo apt-get install -y libffi-dev
/usr/local/bin/sudo: Permission denied.

この通り、拒否されてしまいます。諸々調べた結果下記の方法でインストール出来ました。

問題発生2(INFO: Could not locate ffi libs and/or headers)

めでたく libffi をインストール出来たので Python をインストールし直しました。が、念のため make のログを確認したところ下記を発見。

INFO: Could not locate ffi libs and/or headers

Failed to build these modules:
_ctypes               _zoneinfo 

直訳すると「ffi libs およびヘッダーが見つからず _ctypes モジュールと _zoneinfo モジュールをビルド出来ませんでした。」とのこと。ショック。

しょうがないのでとりあえず続けて make install しましたが、当然 _ctypes モジュールが無いので「pip3 install mysqlclient」を実行しても前回と全く同じエラーで失敗します。

ModuleNotFoundError: No module named '_ctypes'

調査と原因2(./configure 文の修正)

また海に放り出されました。今回は「INFO: Could not locate ffi libs and/or headers」の文言を頼りに調べました。

こちらのページ(英語)を見たところ、どうやら CPPFLAGS、LDFLAGS、PKG_CONFIG_PATH の設定が必要みたいです。PKG_CONFIG_PATH の設定は libffi のインストールの時に行っていたので、取り敢えず CPPFLAGS と LGFLAGS だけでやってみます。

python-3.9.0.tgz は残して他を消し、再度下記の「./configure」文で Python のインストールを試してみます。

./configure --prefix=$HOME/local/python/ --with-system-ffi LDFLAGS="-L $HOME/local/lib/" CPPFLAGS="-I $HOME/local/include/"
項目雑なメモ
--prefixPython3 をインストールする場所
--with-system-ffilibffi のシステムバージョンへの接続を有効にするスイッチ。
CPPFLAGSCプリプロセッサのオプション
include パスを入れるっぽい?
LDFLAGSリンク用のディレクトリを指定する。
lib フォルダを入れるっぽい?

解決(mysqlclient インストール成功)

上記の「./configure」文のあとで make を実行しました。そしてログを確認すると下記の通り _ctypes のエラーはなくなりました。_zoneinfo は何かよくわかりませんし特に今回必要だとも思ってないので無視します。

Failed to build these modules:
_zoneinfo

今回は「pip3 install mysqlclient」も無事成功しました。

% pip3 install mysqlclient
Collecting mysqlclient
  Using cached mysqlclient-2.0.3.tar.gz (88 kB)
Using legacy 'setup.py install' for mysqlclient, since package 'wheel' is not installed.
Installing collected packages: mysqlclient
    Running setup.py install for mysqlclient ... done
Successfully installed mysqlclient-2.0.3
WARNING: You are using pip version 20.2.3; however, version 20.3.3 is available.
You should consider upgrading via the '/home/halekaa/local/python/bin/python3.9 -m pip install --upgrade pip' command.
% 

【2020年1月〜】YouTube 急上昇入りランキング

2021 年第 1 四半期の YouTube 急上昇動画数をチャンネル別にランキング形式で掲載しています。

チャンネル名ランクイン動画数
東海オンエア36 動画
Fischer's-フィッシャーズ-14 動画
コムドット10 動画
ジャニーズJr.チャンネル9 動画
BANDAI NAMCO Arts Channel9 動画
48-フォーエイト8 動画
すとぷりちゃんねる8 動画
ヒカル(Hikaru)8 動画
東海オンエアの控え室8 動画
虎バン 阪神タイガース応援チャンネル ABCテレビ公式7 動画
朝倉未来 Mikuru Asakura7 動画
THE PAGE(ザ・ページ)7 動画
HIROYA x 大雅チャンネル6 動画
貴ちゃんねるず6 動画
Snow Man6 動画
きまぐれクックKimagure Cook6 動画
Ayase / YOASOBI6 動画
THE FIRST TAKE6 動画
両学長 リベラルアーツ大学6 動画
瀬戸弘司 / Koji Seto6 動画
avex5 動画
PROWRESTLING SHIBATAR ZZ5 動画
Nintendo 公式チャンネル5 動画
my channel【白石麻衣 公式】5 動画
きまぐれクックのサボり場5 動画
ジャルジャルアイランド JARUJARU ISLAND5 動画
かす5 動画
ポケモン公式YouTubeチャンネル5 動画
前田日明チャンネル5 動画
SixTONES5 動画
カジサック KAJISAC5 動画
Fischer's-セカンダリ-5 動画
ぷろたん日記5 動画
中井学ゴルフチャンネル5 動画
マルコス 釣り名人への道5 動画
もちまる日記5 動画
PRODUCE 101 JAPAN SEASON25 動画
TBS公式 YouTuboo5 動画
テレビ東京スポーツ5 動画
堀口恭司/Kyoji Horiguchi4 動画
まあたその「ほぼメインチャンネル」4 動画
さんこいち4 動画
さしはらちゃんねる4 動画
あいり4 動画
内山高志KOチャンネル4 動画
Apex Legends4 動画
サッポロ一番 公式4 動画
ABEMA報道リアリティーショー アベプラ【公式】4 動画
ABEMA 今日、好きになりました。【公式】4 動画
丸山礼チャンネル4 動画

さくらレンタルサーバーに libffi をインストールする

  1. SSH でサーバーに接続
  2. ファイルのダウンロードと解凍
  3. インストール
  4. インストール後の設定

SSH でサーバーに接続

% ssh abcabc@abcabc.sakura.ne.jp
abcabc@abcabc.sakura.ne.jp's password: 

ファイルのダウンロードと解凍

ダウンロード用のフォルダを作成

ファイルをダウンロードする前に、ダウンロード用のフォルダを作ります。下記のコマンドで「work」フォルダとその配下に「libffi」フォルダを作成します。

% mkdir -p ~/work/libffi

wget でファイルをダウンロード

作成した「libffi」フォルダに移動して、圧縮ファイルをダウンロードします。

% cd work/libffi
% wget ftp://sourceware.org/pub/libffi/libffi-3.2.1.tar.gz

*初めは最新の「libffi-3.3.tar.gz」で進めたのですが後述の make のところで下記のエラーを返され、すぐに原因も分からなかったので一旦全部ファイルを削除して「libffi-3.2.1.tar.gz」で再チャレンジしました。

gcc: warning: '-x assembler-with-cpp' after last input file has no effect
gcc: No input files specified
*** [libffi.map] Error code 1

上記の wget コマンドを実行してから ls を実行すると圧縮ファイルがダウンロードされたのが確認できます。

% ls
libffi-3.2.1.tar.gz
% 

ファイルを解凍する

ダウンロードした圧縮ファイルを解凍します。

% tar xvfz libffi-3.2.1.tar.gz

ファイルが解凍され、元々ダウンロードした圧縮ファイルとは別に「libffi-3.2.1」という名前のフォルダが作成されています。

インストール

「libffi-3.2.1」のフォルダへ移動し ./configure を実行します。prefix でインストール先を指定します。

% cd libffi-3.2.1
% ./configure --prefix=$HOME/local/libffi/3_2_1

実行するとプロセスが走ってドバドバとターミナルに表示されるので入力待ちになるのを待ちます。

make そして make install を順に実行します。

% make
% make install

.configure の prefix で指定した場所にインストールされました。

インストール後の設定

シンボリックリンクの作成

% mkdir -p ~/local/include
% ln -s $HOME/local/libffi/3_2_1/lib/libffi-3.2.1/include/ffi.h $HOME/local/include/
% ln -s $HOME/local/libffi/3_2_1/lib/libffi-3.2.1/include/ffitarget.h $HOME/local/include/

% mkdir -p ~/local/lib
% ln -s $HOME/local/libffi/3_2_1/lib/libffi.a $HOME/local/lib/
% ln -s $HOME/local/libffi/3_2_1/lib/libffi.la $HOME/local/lib/
% ln -s $HOME/local/libffi/3_2_1/lib/libffi.so $HOME/local/lib/
% ln -s $HOME/local/libffi/3_2_1/lib/libffi.so.6 $HOME/local/lib/

% mkdir -p ~/local/lib/pkgconfig/
% ln -s $HOME/local/libffi/3_2_1/lib/pkgconfig/libffi.pc $HOME/local/lib/pkgconfig/

上記を実行すると下記の様に local 配下に include、lib、lib > pkgconfig が作成され、その配下のシンボリックリンクも確認できます。

環境変数の設定

シンボリックリンクを作成したのでそれぞれ LD_LIBRARY_PATH と PKG_CONFIG_PATH に追加します。他のソースをビルドするときやコマンド実行するときに役立ちます。

シェルの種類ユーザプロファイル
Bourne シェル (sh) または Korn シェル (ksh).profile
Bourne Again シェル (bash).bash_profile
C シェル (csh).login と .cshrc
TC シェル (tcsh).tcshrc と .cshrc
Z シェル (zsh).zlogin と .zshrc

今回はサーバーのシェルが csh なので .cshrc を編集して環境変数を設定します。

.cshrc の編集

% cd ~/
% vi .cshrc

.cshrc に下記を追記します。

setenv  LD_LIBRARY_PATH $HOME/local/lib
setenv  PKG_CONFIG_PATH $HOME/local/lib/pkgconfig

.cshrc で追記した内容を反映させます。

% source ~/.cshrc
% rehash

echo コマンドで確認すると、指定したパスが表示されます。

% echo $LD_LIBRARY_PATH
/home/abcabc/local/lib
% echo $PKG_CONFIG_PATH
/home/abcabc/local/lib/pkgconfig

以上で libffi のインストール作業は完了です。

LD_LIBRARY_PATH と PKG_CONFIG_PATH

LD_LIBRARY_PATH 変数

LD_LIBRARY_PATHは、アプリケーションがリンクされている動的共有ライブラリを検索する際の対象ディレクトリを動的リンクローダーに指示します。複数のディレクトリをコロン (:) で区切ったもので、コンパイルされた検索パスと標準の場所(大抵 /lib、/usr/lib 等)の前に検索されます。

PKG_CONFIG_PATH 変数

pkg-config は、プログラムのコンパイルとシステムにインストールされているライブラリとの接続に必要な情報を提供します。
この情報は .pc ファイルに保存されており、pkg-config ツールで認識されている特定の場所にあります。

pkg-config が .pc ファイルを検索する際、デフォルトでは /usr/lib/pkgconfig と /usr/share/pkgconfig を検索します。しかし、一部のローカルモジュールは /usr/local などの別のプレフィックスにインストールされる場合があるため、PKG_CONFIG_PATH 変数で検索対象のパスを追加します。

【2020年10月〜12月】YouTube 急上昇入りランキング

2020 年第 4 四半期の YouTube 急上昇動画数をチャンネル別にランキング形式で掲載しています。

チャンネル名ランクイン動画数
東海オンエア53 動画
M-1グランプリ18 動画
すとぷりちゃんねる16 動画
ジェルOfficial14 動画
スマなろアニメ14 動画
てんちむCH/ tenchim12 動画
Fischer's-フィッシャーズ-11 動画
ラブライブ!シリーズ公式チャンネル11 動画
スマイリー11 動画
フェルミ研究所 FermiLab11 動画
しばなんといっしょ!10 動画
はじめしゃちょー(hajime)10 動画
ジャニーズJr.チャンネル9 動画
JO19 動画
JYP Entertainment9 動画
Mnet K-POP9 動画
かす9 動画
ゆうこすモテちゃんねる8 動画
モンスト(モンスターストライク)公式8 動画
古川優香8 動画
TWICE JAPAN OFFICIAL YouTube Channel8 動画
THE FIRST TAKE8 動画
仲里依紗です。8 動画
朝倉未来 Mikuru Asakura8 動画
カジサック KAJISAC8 動画
ARASHI8 動画
もちまる日記8 動画
宮迫ですッ!【宮迫博之】8 動画
しばなんチャンネル8 動画
がくちゃん GACKT official YouTube8 動画
佐藤 健 / Satoh Takeru8 動画
/谷やん谷崎鷹人8 動画
銀魂チャンネル【公式】8 動画
JJコンビ8 動画
48-フォーエイト8 動画
東海オンエアの控え室7 動画
ハラミちゃん〈harami_piano〉7 動画
SEVENTEEN7 動画
ぺえ7 動画
Apex Legends7 動画
きまぐれクックKimagure Cook7 動画
タナカガ7 動画
ヒカル(Hikaru)7 動画
スカイピースの平和島7 動画
THE ROLAND SHOW【公式】7 動画
Snow Man7 動画
アニプレックス7 動画
kouichitv7 動画
手越祐也チャンネル7 動画
まあたその「ほぼメインチャンネル」7 動画

【Python】Mac に MySQL モジュールをインストールする方法

環境

OS: macOS Catalina バージョン 10.15.4
Python: Python 3.8.3

やりたいこと

Python で MySQLdb モジュールを使える様にしたい。

mysql をインストール

まず Homebrew で MySQL をインストールする必要があります。これをしていないとこの後 pip で「mysqlclient」のインストールができません。「brew install mysql」を実行します。

(scraping) % brew install mysql
Updating Homebrew...
==> Auto-updated Homebrew!
Updated 1 tap (homebrew/core).
==> New Formulae
acl2                       heksa                      nfpm
act                        httpx                      ngs
airshare                   hy                         notmuch-mutt
alsa-lib                   i686-elf-binutils          numcpp
amp                        i686-elf-gcc               oci-cli
apidoc                     idris2                     omake
arb                        infracost                  openfst
argo                       inja                       oq
argocd                     inko                       ormolu
arrayfire                  ioctl                      ory-hydra
asimov                     jerryscript                osi
asroute                    jimtcl                     osm
athenacli                  jinx                       packetbeat
austin                     jobber                     packr
awsweeper                  jsonnet-bundler            pandoc-include-code
blogc                      k9s                        pandocomatic
bombadillo                 kde-karchive               parallel-hashmap
bond                       kde-kdoctools              periscope
borgbackup                 kde-ki18n                  pipgrip
box2d                      kde-threadweaver           po4a
buildozer                  kona                       podman
c7n                        kondo                      postgresql@12
cadence                    ksync                      prometheus-cpp
carton                     kubie                      promtail
cassowary                  ladspa-sdk                 protoc-gen-go-grpc
castget                    latexindent                protoc-gen-gogo
cbc                        ldpl                       protoc-gen-gogofaster
cdktf                      leaf                       pwncat
cgl                        libaio                     python@3.7
chalk-cli                  libcouchbase@2             python@3.9
charge                     libdmx                     reg
chart-testing              libdrm                     rgf
choose-rust                libfontenc                 rqlite
chrony                     libfs                      rust-analyzer
clair                      libgccjit                  rustscan
clang-format@8             libgnt                     s2n
cli11                      libhandy                   saltwater
cloud-nuke                 libice                     scw@1
cloudformation-cli         libirecovery               sdns
cloudformation-guard       libmnl                     server-go
coconut                    libnetfilter-queue         shallow-backup
colfer                     libnetworkit               sheldon
commitizen                 libnfnetlink               shtools
copilot                    liboqs                     silicon
coredns                    libpciaccess               simdjson
cortex                     libpthread-stubs           skylighting
cpio                       libseccomp                 sleef
cpm                        libsm                      smlpkg
cpr                        libx11                     snap
croaring                   libxau                     so
croc                       libxaw                     solidity
cubejs-cli                 libxaw3d                   sonic
cvs-fast-export            libxcb                     sponge
datasette                  libxcomposite              sqlite-utils
dbdeployer                 libxcursor                 standardese
diskonaut                  libxdamage                 staticcheck
dnsprobe                   libxdmcp                   structurizr-cli
doctest                    libxext                    subfinder
dosbox-staging             libxfixes                  termcolor
dotnet                     libxfont                   terraform-ls
duckscript                 libxft                     terraform@0.12
eksctl                     libxi                      terrascan
eleventy                   libxinerama                tfsec
empty                      libxkbfile                 thanos
envoy                      libxmu                     toot
fava                       libxpm                     torchvision
fblog                      libxrandr                  tre-command
fennel                     libxrender                 trunk
fetch                      libxres                    ugrep
flank                      libxscrnsaver              uptoc
fleet-cli                  libxshmfence               usb.ids
flit                       libxt                      util-macros
folderify                  libxtst                    vapor
font-util                  libxv                      vcpkg
foreman                    libxvmc                    vgrep
fpart                      libxxf86dga                vivid
fpdns                      libxxf86vm                 vlang
functionalplus             litecli                    volk
gateway-go                 localstack                 vsearch
gcc@9                      logcli                     vtk@8.2
git-hooks-go               loki                       webify
git-hound                  lunchy                     wgcf
gitql                      lunchy-go                  wownero
gitui                      macos-trash                wren
gluon                      mandown                    wren-cli
go@1.14                    mariadb@10.4               x86_64-elf-gdb
gofish                     marked                     xcb-proto
golangci-lint              mask                       xdpyinfo
gostatic                   matplotplusplus            xorgproto
gradle-profiler            mhonarc                    xtrans
gravity                    microplane                 yj
grpcui                     naabu                      z.lua
gulp-cli                   nanorc                     zoxide
halide                     nest                       zsh-you-should-use
hashlink                   networkit
hasura-cli                 never
==> Updated Formulae
Updated 4645 formulae.
==> Renamed Formulae
elasticsearch@6.8 -> elasticsearch@6
gst-validate -> gst-devtools
interactive-rebase-tool -> git-interactive-rebase-tool
jfrog-cli-go -> jfrog-cli
kibana@6.8 -> kibana@6
mkl-dnn -> onednn
==> Deleted Formulae
baidupcs-go         elasticsearch@5.6   marathon-swift      unravel
biogeme             highlighting-kate   python              urbit
cargo-completion    i386-elf-grub       residualvm          wpscan
cryptopp            kibana@5.6          sflowtool           xu4
elasticsearch@2.4   lumo                tomee-jax-rs

==> Downloading https://homebrew.bintray.com/bottles/openssl%401.1-1.1.1h.catali
==> Downloading from https://d29vzk4ow07wi7.cloudfront.net/4e5357c0cfd55cfa4ef0b
######################################################################## 100.0%
==> Downloading https://homebrew.bintray.com/bottles/protobuf-3.13.0.catalina.bo
==> Downloading from https://d29vzk4ow07wi7.cloudfront.net/af2990ba0a6e5588ef2af
######################################################################## 100.0%
==> Downloading https://homebrew.bintray.com/bottles/mysql-8.0.21_1.catalina.bot
==> Downloading from https://d29vzk4ow07wi7.cloudfront.net/81e92d0df39edaff415e7
######################################################################## 100.0%
==> Installing dependencies for mysql: openssl@1.1 and protobuf
==> Installing mysql dependency: openssl@1.1
==> Pouring openssl@1.1-1.1.1h.catalina.bottle.tar.gz
==> Caveats
A CA file has been bootstrapped using certificates from the system
keychain. To add additional certificates, place .pem files in
  /usr/local/etc/openssl@1.1/certs

and run
  /usr/local/opt/openssl@1.1/bin/c_rehash

openssl@1.1 is keg-only, which means it was not symlinked into /usr/local,
because macOS provides LibreSSL.

If you need to have openssl@1.1 first in your PATH run:
  echo 'export PATH="/usr/local/opt/openssl@1.1/bin:$PATH"' >> ~/.zshrc

For compilers to find openssl@1.1 you may need to set:
  export LDFLAGS="-L/usr/local/opt/openssl@1.1/lib"
  export CPPFLAGS="-I/usr/local/opt/openssl@1.1/include"

==> Summary
🍺  /usr/local/Cellar/openssl@1.1/1.1.1h: 8,067 files, 18.5MB
==> Installing mysql dependency: protobuf
==> Pouring protobuf-3.13.0.catalina.bottle.tar.gz
==> Caveats
Emacs Lisp files have been installed to:
  /usr/local/share/emacs/site-lisp/protobuf
==> Summary
🍺  /usr/local/Cellar/protobuf/3.13.0: 266 files, 19.8MB
==> Installing mysql
==> Pouring mysql-8.0.21_1.catalina.bottle.tar.gz
==> /usr/local/Cellar/mysql/8.0.21_1/bin/mysqld --initialize-insecure --user=ken
==> Caveats
We've installed your MySQL database without a root password. To secure it run:
    mysql_secure_installation

MySQL is configured to only allow connections from localhost by default

To connect run:
    mysql -uroot

To have launchd start mysql now and restart at login:
  brew services start mysql
Or, if you don't want/need a background service you can just run:
  mysql.server start
==> Summary
🍺  /usr/local/Cellar/mysql/8.0.21_1: 290 files, 291.2MB
==> `brew cleanup` has not been run in 30 days, running now...
Removing: /Users/xxxxxxxx/Library/Caches/Homebrew/gettext--0.20.2_1.catalina.bottle.tar.gz... (8.4MB)
Removing: /Users/xxxxxxxx/Library/Caches/Homebrew/libidn2--2.3.0.catalina.bottle.tar.gz... (233.6KB)
Removing: /Users/xxxxxxxx/Library/Caches/Homebrew/libunistring--0.9.10.catalina.bottle.tar.gz... (1.4MB)
Removing: /usr/local/Cellar/openssl@1.1/1.1.1g... (8,059 files, 18MB)
Removing: /Users/xxxxxxxx/Library/Caches/Homebrew/openssl@1.1--1.1.1g.catalina.bottle.tar.gz... (5.3MB)
Removing: /Users/xxxxxxxx/Library/Caches/Homebrew/tree--1.8.0.catalina.bottle.tar.gz... (49.5KB)
Removing: /Users/xxxxxxxx/Library/Caches/Homebrew/wget--1.20.3_2.catalina.bottle.tar.gz... (1.4MB)
Removing: /Users/xxxxxxxx/Library/Logs/Homebrew/tree... (64B)
Removing: /Users/xxxxxxxx/Library/Logs/Homebrew/wget... (64B)
Removing: /Users/xxxxxxxx/Library/Logs/Homebrew/libidn2... (64B)
Removing: /Users/xxxxxxxx/Library/Logs/Homebrew/libunistring... (64B)
Removing: /Users/xxxxxxxx/Library/Logs/Homebrew/gettext... (64B)
Removing: /Users/xxxxxxxx/Library/Logs/Homebrew/openssl@1.1... (64B)
Pruned 1 symbolic links and 2 directories from /usr/local
==> Caveats
==> openssl@1.1
A CA file has been bootstrapped using certificates from the system
keychain. To add additional certificates, place .pem files in
  /usr/local/etc/openssl@1.1/certs

and run
  /usr/local/opt/openssl@1.1/bin/c_rehash

openssl@1.1 is keg-only, which means it was not symlinked into /usr/local,
because macOS provides LibreSSL.

If you need to have openssl@1.1 first in your PATH run:
  echo 'export PATH="/usr/local/opt/openssl@1.1/bin:$PATH"' >> ~/.zshrc

For compilers to find openssl@1.1 you may need to set:
  export LDFLAGS="-L/usr/local/opt/openssl@1.1/lib"
  export CPPFLAGS="-I/usr/local/opt/openssl@1.1/include"

==> protobuf
Emacs Lisp files have been installed to:
  /usr/local/share/emacs/site-lisp/protobuf
==> mysql
We've installed your MySQL database without a root password. To secure it run:
    mysql_secure_installation

MySQL is configured to only allow connections from localhost by default

To connect run:
    mysql -uroot

To have launchd start mysql now and restart at login:
  brew services start mysql
Or, if you don't want/need a background service you can just run:
  mysql.server start

長々とログが出ましたが、入力待ちになったら which コマンドで mysql がインストールされたのを確認します。

(scraping) % which mysql
/usr/local/bin/mysql

/usr/local/bin/mysql にインストールされています。

MySQL の動作を確認

MySQL を起動

「mysql.server start」と入力して MySQL を起動してみます。

% mysql.server start
Starting MySQL
.. SUCCESS! 
% 

無事起動しました。

MySQL をシャットダウン

「mysql.server stop」でシャットダウンすることができます。

% mysql.server stop
Shutting down MySQL
.. SUCCESS!
%

mysqlclient をインストール

pip で mysqlclient をインストールします。

(scraping) % pip install mysqlclient
Collecting mysqlclient
  Using cached https://files.pythonhosted.org/packages/a5/e1/e5f2b231c05dc51d9d87fa5066f90d1405345c54b14b0b11a1c859020f21/mysqlclient-2.0.1.tar.gz
Installing collected packages: mysqlclient
  Running setup.py install for mysqlclient ... done
Successfully installed mysqlclient-2.0.1
WARNING: You are using pip version 19.2.3, however version 20.2.3 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.
(scraping) % 

MySQLdb モジュールが使えることを確認

Python で MySQLdb モジュールがインポートできることを確認して完了です。

>>> import MySQLdb
>>> 

【Python】さくらレンタルサーバーに requests モジュールをインストール

いきなり request をインポートしようとすると「request モジュールがありません」とのことでエラーが出てしまいます。

>>> import requests
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'requests'

なので一旦 Python は exit() します。そして pip3 で request をインストール。

>>> exit()
% pip3 install requests

すると下記の様に諸々のダウンロードが実行され一瞬で入力待ち状態に戻ります。

% pip3 install requests
Collecting requests
  Downloading requests-2.24.0-py2.py3-none-any.whl (61 kB)
     |████████████████████████████████| 61 kB 692 kB/s 
Collecting certifi>=2017.4.17
  Downloading certifi-2020.6.20-py2.py3-none-any.whl (156 kB)
     |████████████████████████████████| 156 kB 6.7 MB/s 
Collecting idna<3,>=2.5
  Downloading idna-2.10-py2.py3-none-any.whl (58 kB)
     |████████████████████████████████| 58 kB 7.5 MB/s 
Collecting chardet<4,>=3.0.2
  Downloading chardet-3.0.4-py2.py3-none-any.whl (133 kB)
     |████████████████████████████████| 133 kB 16.4 MB/s 
Collecting urllib3!=1.25.0,!=1.25.1,<1.26,>=1.21.1
  Downloading urllib3-1.25.10-py2.py3-none-any.whl (127 kB)
     |████████████████████████████████| 127 kB 20.1 MB/s 
Installing collected packages: certifi, idna, chardet, urllib3, requests
Successfully installed certifi-2020.6.20 chardet-3.0.4 idna-2.10 requests-2.24.0 urllib3-1.25.10
% 

入力待ちになったら Python3 を起動。

% python3

そしてそのまま request をインポートしてみます。

>>> import requests
>>>   

今回はエラーが出ず入力待ち状態になりました。試しにそのまま Yahoo! のソースコードを表示してみます。

>>> import requests
>>> r = requests.get('http://yahoo.com/')
>>> r.text
'<!DOCTYPE html>\n<html id="atomic" lang="en-US" class="atomic   l-out Pos-r https fp fp-v2 fp-default mini-uh-on uh-topbar-on ltr desktop Desktop bkt201">\n<head>\n    <meta http-equiv="X-UA-Compatible" content="IE=edge">\n    \n    <title>Yahoo</title><meta http-equiv="x-dns-prefetch-control" content="on"><link rel="dns-prefetch" href="//s.yimg.com"><link rel="preconnect" href="//s.yimg.com">

問題なさそうですね。これで request のインストールは完了です。

さくらレンタルサーバに Python3 をインストールする方法

さくらレンタルサーバには Python2 系が入っているのですが、Python2 はもう推奨されていないので 3 系をインストールする方法を紹介します。ちなみに私は Mac ユーザーなのでターミナルを使用しています。

  1. ssh でさくらレンタルサーバにログイン
  2. ダウンロード用のフォルダを作成
  3. wget でファイルをダウンロード
  4. ファイルを解凍する
  5. インストール
  6. パスを通す
  7. 設定を反映
  8. パスが通ったことを確認して完了

ssh でさくらレンタルサーバにログイン

まずはターミナルを立ち上げ、ssh でさくらレンタルサーバにログインします。

Last login: Sun Oct 11 10:43:12 on ttys000
% ssh XXXXXX@XXXXXX.sakura.ne.jp
XXXXXX@XXXXXX.sakura.ne.jp's password: 

ダウンロード用のフォルダを作成

ファイルをダウンロードする前に、ダウンロード用のフォルダを作っておきます。下記のコマンドで「work」フォルダとその配下に「python3」フォルダを作成します。

% mkdir -p ~/work/python3

FTPクライアントで見てみると下記の様に各フォルダが作成されているのが確認できます。

wget でファイルをダウンロード

% cd ~/work/python3
% wget --no-check-certificate https://www.python.org/ftp/python/3.9.0/Python-3.9.0.tgz

ファイルがダウンロードされ、下記の様に入力待ちになれば無事ダウンロード完了です。

% wget --no-check-certificate https://www.python.org/ftp/python/3.9.0/Python-3.9.0.tgz
--2020-10-11 12:39:03--  https://www.python.org/ftp/python/3.9.0/Python-3.9.0.tgz
Resolving www.python.org... 151.101.88.223, 2a04:4e42:15::223
Connecting to www.python.org|151.101.88.223|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 26724009 (25M) [application/octet-stream]
Saving to: 'Python-3.9.0.tgz'

Python-3.9.0.tgz    100%[=====================>]  25.49M  43.9MB/s   in 0.6s   

2020-10-11 12:39:03 (43.9 MB/s) - 'Python-3.9.0.tgz' saved [26724009/26724009]

% 

念のため覗いてみると、先ほど作成した「python3」フォルダのなかに「Python-3.9.0.tgz」のファイルがダウンロードされているのが分かります。

ファイルを解凍する

% tar zxf Python-3.9.0.tgz

ファイルが解凍され、元々ダウンロードした圧縮ファイルとは別に「Python-3.9.0」という名前のフォルダが作成されています。

インストール

解凍されたフォルダ「Python-3.9.0」に移動します。

% cd ./Python-3.9.0

次に ./configure を実行しますが、その際 prefix を使ってインストールするディレクトリを指定します。

% ./configure --prefix=$HOME/local/python/

実行するとプロセスが走ってドバドバとターミナルに表示されますが、下記が表示されて入力待ちの状態になったら完了です。

creating Modules/Setup.local
creating Makefile

「make」を実行します。

%  make

しばらくプロセスが走るので入力待ちになるまで待ちます。次に「make install」を実行します。

%  make install

またプロセスが走るので最後下記の様な表示が出て入力待ちになるまで待ちます。

Installing collected packages: setuptools, pip
  WARNING: The script easy_install-3.9 is installed in '/home/XXXXXX/local/python/bin' which is not on PATH.
  Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location.
  WARNING: The scripts pip3 and pip3.9 are installed in '/home/XXXXXX/local/python/bin' which is not on PATH.
  Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location.
Successfully installed pip-20.2.3 setuptools-49.2.1
% 

実は上のログに2箇所「WARNING」として警告が表示されているのですが、その内容が以下の通り。

WARNING:スクリプトeasy_install-3.9は、「PATH」にない「/home/XXXXXX/local/python/bin」にインストールされています。このディレクトリを「PATH」に追加することを検討してください。
WARNING:スクリプトpip3およびpip3.9は、「PATH」にない「/home/XXXXXX/local/python/bin」にインストールされています。このディレクトリを「PATH」に追加することを検討してください。

これは後ほど .cshrc ファイルを編集して解決します。

local > python というディレクトリが作られ、さらにその配下に様々なフォルダが作られています。

パスを通す

python3 と pip3 のインストール自体は完了しましたが、この状態だとまだ python3 や pip3 と言ったコマンドを直接使うことができません。いわゆる「パスが通っていない」状態です。「which」コマンドを実行しても下記の通りエラーが返ってきます。

% which python3
python3: Command not found.
% which pip3
pip3: Command not found.

python3 と pip3 が両方とも「$HOME/local/python/bin」にインストールされている状態です。

.cshrc ファイルを編集することでパスを通しますが、この作業をする前に必ず .cshrc のバックアップをとっておきましょう。

% cd ~/
% vi .cshrc

.cshrc の内容がターミナルに表示されます。

# $FreeBSD: src/share/skel/dot.cshrc,v 1.14.6.1 2008/11/25 02:59:29 kensmith Exp
 $
#
# .cshrc - csh resource script, read at beginning of execution by each shell
#
# see also csh(1), environ(7).
#

alias h         history 25
alias j         jobs -l
alias la        ls -a
alias lf        ls -FA
alias ll        ls -lA

# A righteous umask
umask 22

set path = (/sbin /bin /usr/sbin /usr/bin /usr/local/sbin /usr/local/bin $HOME/bin)

setenv  EDITOR  vi
setenv  PAGER   more
setenv  BLOCKSIZE       K
setenv  PKG_DBDIR       ~/db/pkg

if ($?prompt) then
        # An interactive shell -- set some stuff up
        set filec
        set history = 100
        set savehist = 100
        set mail = (/var/mail/$USER)
        if ( $?tcsh ) then
                bindkey "^W" backward-delete-word
                bindkey -k up history-search-backward
                bindkey -k down history-search-forward
        endif
endif

このファイルの最後に「set path = ($path $HOME/local/python/bin)」を追記したいのですが、手順が少しややこしいので下記の記事などを参考にしつつ行ってください。

以下の様に、ファイルの一番最後に一行だけ追記しました。

                bindkey "^W" backward-delete-word
                bindkey -k up history-search-backward
                bindkey -k down history-search-forward
        endif
endif
set path = ($path $HOME/local/python/bin)

設定を反映

.cshrc で変更した内容を反映させます。

% source ~/.cshrc
% rehash

パスが通ったことを確認して完了

パスを通す前はエラーが返ってきた「which」コマンドですが、今回はきちんと python3、pip3 のパスが表示されます。

% which python3
/home/XXXXXX/local/python/bin/python3
% which pip3
/home/XXXXXX/local/python/bin/pip3
% 

バージョン情報もきちんと表示されます。

% python3 --version
Python 3.9.0
% pip3 --version
pip 20.2.3 from /home/XXXXXX/local/python/lib/python3.9/site-packages/pip (python 3.9)
% 

最後に圧縮ファイルのダウンロードに使ったフォルダとファイルを削除して完了です。

% rm -r ~/work/python3