Tambourine作業メモ

主にスキル習得のためにやった作業のメモ。他人には基本的に無用のものです。

個人のドメインを取得した

20年この業界で仕事をし、いろいろなWebベースのシステムのインフラ部分に関わって、おおよそのシステムの勘所は掴んでいるつもりだ。だけども、仕事が社内向けシステムに偏りがちだということもあって、SEOなんかはまったくわからない。特に、最近不勉強で良くないなと思っているのがDNSである。出入りの業者がお客様のDNSを触ることはないので、ドメインの管理の仕組みやDNSのレコードについてはさっぱりわからない。この点に関しては、「レンタルサーバWordpressを建ててブログを書こう!あなたもすぐに収益化!」というようなサイトを見て見よう見まねでWebサーバを立てている業界外の皆さんより数段劣っている自覚がある。プロとして恥ずかしい。

WordpressのようなCMSについてもそうである。CMSでやれるようなWebシステムを汎用フレームワークを使ったり、なんならフレームワークを使わなかったりして自力で実装することは出来るんだけども、Wordpressを使ってお手軽Webサーバを立てることはやったことがない。なんなら、何が出来るのか理解をしていない。Wordpressでちゃちゃっとできるようなことをするのに、Spring bootを持ってきがちなのである。プロとして恥ずかしい。

さらに、長年ブログを書いてきたココログが、社内のDNSから「怪しいサイト」扱いをされて名前解決出来なくなるという悲しい事件が起きた。もちろん、「ココログ怪しくないよ」と社内の部門に連絡してもいいのだが、本当に怪しくないのか別に私が保証できるわけでもない。ともかく、自分のブログに書いたことを社内で連携できなくなったのはつらい。引っ越しを考えるべきである。HerokuのF1ラップタイムPDFをCSVに変換するツールの移行先も考えたい。

いろいろ考えると、これは自分でサイトを立ち上げるべきである。やっていることがざっと25年遅れな気がして恥ずかしいが、今回の記事はここまでに恥ずかしい点はたくさんあったのでもうしょうがないのである。

まず、第1歩として、ドメインを取得することにした。

勝手がわからないんだけども、ぐぐるととにかくいろんなレジストラの名前が出てくる。お名前.comとかがとにかくめちゃめちゃ推されている。それはGoogleに大量のお金を払っているからなのかもしれないが、とりあえず、有名どころを触ってみるのは経験としてよいことなので、とりあえず目に付いたところから買えばいいかなと思う。後の引っ越しのことも考えて、今回はサーバを置くところとドメインを管理するところはとりあえず別にしてみることにした。

が、ググりまくっていると「とにかく、お名前.comはメールが死ぬほどくるのでむかつく」という評判をみた。ああー・・・、いわゆる楽天状態かー。なんとなく、日本のスーパーのチラシみたいなWebサイトを作っているような業者はおしなべてメールを死ぬほど送ってきて迷惑である。関わりたくない。どうしよう。でも、このへん、何にも知らないので日本語が通じるところでやりたい・・・。

という葛藤のあげく、Google Domainsから買うことにした。お値段はそこそこだが、とりあえず年3000円ぐらいは勉強代で構わない。あっという間に買えた。あっという間に買えたけど、これをどうやってレンタルサーバにつくるサイトと紐付けるのは未だによくわかっていない。転びながらやっていくことにする。次はサーバを建てないと。

Herokuのしょぼいアプリが動かなくなっていたので対応した

何年か前の話だが、某所で某F1関係者がFIAが提供しているラップチャートのPDFから、グラフを書くためにExcelに各ドライバーのラップタイムをコピペするのがめんどいと愚痴っているのを聞き、PDFを読んでCSVを返すRubyスクリプトを作って提供することにした。とはいえ、Rubyスクリプトを実行してねというのも乱暴で、どこかでWebツールとして提供するのが良かろうということになり、CSSもなんにもないWeb画面で各グランプリをリストし、クリックするとCSVがダウンロードされるだけの手抜きアプリを作り、Herokuの無料枠で提供していた(事実上、ユーザーが1名しかいないアプリなので、それで十分だった)。Herokuのガイドに従って、sinatraで制御してた。

PDFの入手リンク先を毎戦確認したり、FIAが気分で変えたPDFのフォーマットに対応したりで、ちょいちょいメンテナンスが発生したりはするものの概ね機嫌良く動いてはいた。だが、Rubyのバージョンが古くなって更新しろよと警告がでていたりしたのだが、放置していた。というのも、Herokuは無料枠がなくなってしまうということがあって、どこかに引っ越さなくてはいけないなと思っていたから。しかし、ここのところ仕事に追いまくられて対応出来ず、ついに今週は2023年の開幕戦である。Herokuのまましばらく運用するほかない。

というわけで、去年の最終戦以来、アプリをビルドしてみたところ、動かない。ごちゃごちゃといろいろ対応する必要があったので、メモしておく。

> git push
Enumerating objects: 7, done.
Counting objects: 100% (7/7), done.
Delta compression using up to 8 threads
Compressing objects: 100% (4/4), done.
Writing objects: 100% (4/4), 378 bytes | 378.00 KiB/s, done.
Total 4 (delta 2), reused 0 (delta 0), pack-reused 0
remote: Compressing source files... done.
remote: Building source:
remote: 
remote: !   Your app is using the Heroku-18 stack, which reaches end-of-life on April 30th, 2023.
remote: !   
remote: !   Builds on Heroku-18 will not be possible from May 1st, 2023.
remote: !   
remote: !   Please upgrade the stack of your app as soon as possible:
remote: !   https://devcenter.heroku.com/articles/upgrading-to-the-latest-stack
remote: !   
remote: !   Heroku-18 EOL FAQ: https://help.heroku.com/X5OE6BCA/heroku-18-end-of-life-faq
remote: !   
remote: !   THIS IS A ONE-OFF NOTICE. THE NEXT DEPLOY WILL FUNCTION WITHOUT INTERRUPTION.
remote: !   
remote: !   The next warning of this kind will occur in: 7 day(s).
remote: 
To https://git.heroku.com/lit-taiga-21087.git
 ! [remote rejected] master -> master (pre-receive hook declined)
error: failed to push some refs to 'https://git.heroku.com/lit-taiga-21087.git'

Heroku-18スタックはもう使えないから移行しろということらしい。エラーメッセージに出ているFAQを読むと新しいディレクトリに新しいスタック用にアプリを組み立てて・・・となっていて「おおぅ」となった。

が、HerokuのWeb管理画面にいくと以下のようになっていて、ボタンを押せば更新が走ってしまうようだ。私のしょぼいアプリはこれで問題なかった。

> git push
Enumerating objects: 7, done.
Counting objects: 100% (7/7), done.
Delta compression using up to 8 threads
Compressing objects: 100% (4/4), done.
Writing objects: 100% (4/4), 378 bytes | 378.00 KiB/s, done.
Total 4 (delta 2), reused 0 (delta 0), pack-reused 0
remote: Compressing source files... done.
remote: Building source:
remote: 
remote: -----> Building on the Heroku-22 stack
remote: -----> Using buildpack: heroku/ruby
remote: -----> Ruby app detected
remote: -----> Installing bundler 2.3.25
remote: -----> Removing BUNDLED WITH version in the Gemfile.lock
remote: -----> Compiling Ruby/Rack
remote:        Command: 'set -o pipefail; curl -L --fail --retry 5 --retry-delay 1 --connect-timeout 3 --max-time 30 https://heroku-buildpack-ruby.s3.us-east-1.amazonaws.com/heroku-22/ruby-2.7.1.tgz -s -o - | tar zxf - ' failed on attempt 1 of 3.
remote:        Command: 'set -o pipefail; curl -L --fail --retry 5 --retry-delay 1 --connect-timeout 3 --max-time 30 https://heroku-buildpack-ruby.s3.us-east-1.amazonaws.com/heroku-22/ruby-2.7.1.tgz -s -o - | tar zxf - ' failed on attempt 2 of 3.
remote: 
remote:  !
remote:  !     The Ruby version you are trying to install does not exist on this stack.
remote:  !     
remote:  !     You are trying to install ruby-2.7.1 on heroku-22.
remote:  !     
remote:  !     Ruby ruby-2.7.1 is present on the following stacks:
remote:  !     
remote:  !     - heroku-18
remote:  !     - heroku-20
remote:  !     
remote:  !     Heroku recommends you use the latest supported Ruby version listed here:
remote:  !     https://devcenter.heroku.com/articles/ruby-support#supported-runtimes
remote:  !     
remote:  !     For more information on syntax for declaring a Ruby version see:
remote:  !     https://devcenter.heroku.com/articles/ruby-versions
remote:  !
remote:  !     Push rejected, failed to compile Ruby app.
remote: 
remote:  !     Push failed
remote: Verifying deploy...
remote: 
remote: !   Push rejected to lit-taiga-21087.
remote: 
To https://git.heroku.com/lit-taiga-21087.git
 ! [remote rejected] master -> master (pre-receive hook declined)
error: failed to push some refs to 'https://git.heroku.com/lit-taiga-21087.git'

次はRubyが古いと言われている。単純にGemfileのバージョンを3.1.3に書き換えて、Gemfile.lockを消して(する必要があるのか理解出来てない)、bundle installする。

> bundle install
rbenv: version `2.7.1' is not installed (set by /Users/tambara/F1_lap_analysis/.ruby-version)

rbenvでRubyバージョンを固定してあった。パソコンの移行後は手元に2.7.1が入ってない状態。普段、PDF入手先を書き換えてPUSHするだけなのでローカルにRubyが入ってなくてもメンテ出来ていたようだ。

> rbenv local 3.1.3

を実行しておいて、

> bundle install
Fetching https://github.com/sinatra/sinatra.git
Fetching gem metadata from https://rubygems.org/.............
Resolving dependencies...
Using rake 13.0.6
Fetching afm 0.2.2
Using bundler 2.3.26
Fetching ffi 1.15.5
Fetching Ascii85 1.1.0
Fetching diff-lcs 1.5.0
Fetching coderay 1.1.3
Fetching formatador 1.1.0
Fetching rb-fsevent 0.11.2
Fetching lumberjack 1.2.8
Installing formatador 1.1.0
Installing Ascii85 1.1.0
Installing afm 0.2.2
Installing lumberjack 1.2.8
Installing diff-lcs 1.5.0
Installing rb-fsevent 0.11.2
Installing coderay 1.1.3
Fetching nenv 0.3.0
Fetching shellany 0.0.1
Fetching method_source 1.0.0
Fetching thor 1.2.1
Fetching guard-compat 1.2.1
Fetching minitest 5.17.0
Fetching hashery 2.1.2
Installing shellany 0.0.1
Fetching multi_json 1.15.0
Installing nenv 0.3.0
Installing method_source 1.0.0
Using ruby2_keywords 0.0.5
Fetching ruby-rc4 0.1.5
Installing guard-compat 1.2.1
Fetching ttfunk 1.7.0
Fetching rack 2.2.6.2
Installing ffi 1.15.5 with native extensions
Installing thor 1.2.1
Fetching rspec-support 3.12.0
Installing hashery 2.1.2
Fetching tilt 2.1.0
Installing minitest 5.17.0
Fetching notiffany 0.1.3
Installing ruby-rc4 0.1.5
Fetching mustermann 3.0.0
Installing multi_json 1.15.0
Fetching pry 0.14.2
Installing ttfunk 1.7.0
Installing tilt 2.1.0
Fetching guard-minitest 2.4.6
Installing notiffany 0.1.3
Fetching pdf-reader 2.11.0
Installing rack 2.2.6.2
Fetching rack-test 2.0.2
Using rack-protection 3.0.5 from https://github.com/sinatra/sinatra.git (at master@4fc73c3)
Installing rspec-support 3.12.0
Fetching rspec-core 3.12.1
Fetching rspec-expectations 3.12.2
Installing mustermann 3.0.0
Fetching rspec-mocks 3.12.3
Installing guard-minitest 2.4.6
Using sinatra 3.0.5 from https://github.com/sinatra/sinatra.git (at master@4fc73c3)
Fetching sinatra-contrib 3.0.5
Installing pry 0.14.2
Installing rack-test 2.0.2
Installing rspec-expectations 3.12.2
Installing pdf-reader 2.11.0
Installing rspec-core 3.12.1
Installing sinatra-contrib 3.0.5
Installing rspec-mocks 3.12.3
Fetching rspec 3.12.0
Installing rspec 3.12.0
Fetching rb-inotify 0.10.1
Installing rb-inotify 0.10.1
Fetching listen 3.8.0
Installing listen 3.8.0
Fetching guard 2.18.0
Installing guard 2.18.0
Bundle complete! 9 Gemfile dependencies, 40 gems now installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.

改めて、ビルドするためにgit pushする。

> git push
Enumerating objects: 14, done.
Counting objects: 100% (14/14), done.
Delta compression using up to 8 threads
Compressing objects: 100% (8/8), done.
Writing objects: 100% (9/9), 1.23 KiB | 1.23 MiB/s, done.
Total 9 (delta 5), reused 0 (delta 0), pack-reused 0
remote: Compressing source files... done.
remote: Building source:
remote: 
remote: -----> Building on the Heroku-22 stack
remote: -----> Using buildpack: heroku/ruby
remote: -----> Ruby app detected
remote: -----> Installing bundler 2.3.25
remote: -----> Removing BUNDLED WITH version in the Gemfile.lock
remote: -----> Compiling Ruby/Rack
remote: -----> Using Ruby version: ruby-3.1.3
remote:        Purging Cache. Changing stack from heroku-18 to heroku-22
remote: -----> Installing dependencies using bundler 2.3.25
remote:        Running: BUNDLE_WITHOUT='development:test' BUNDLE_PATH=vendor/bundle BUNDLE_BIN=vendor/bundle/bin BUNDLE_DEPLOYMENT=1 bundle install -j4
remote:        Your bundle only supports platforms ["arm64-darwin-22"] but your local platform
remote:        is x86_64-linux. Add the current platform to the lockfile with
remote:        `bundle lock --add-platform x86_64-linux` and try again.
remote:        Bundler Output: Your bundle only supports platforms ["arm64-darwin-22"] but your local platform
remote:        is x86_64-linux. Add the current platform to the lockfile with
remote:        `bundle lock --add-platform x86_64-linux` and try again.
remote: 
remote:  !
remote:  !     Failed to install gems via Bundler.
remote:  !
remote:  !     Push rejected, failed to compile Ruby app.
remote: 
remote:  !     Push failed
remote: Verifying deploy...
remote: 
remote: !   Push rejected to lit-taiga-21087.
remote: 
To https://git.heroku.com/lit-taiga-21087.git
 ! [remote rejected] master -> master (pre-receive hook declined)
error: failed to push some refs to 'https://git.heroku.com/lit-taiga-21087.git'

プラットフォーム設定がおかしいと。親切にコマンドまで提示されているので、その通りやる。

> bundle lock --add-platform x86_64-linux
Fetching gem metadata from https://rubygems.org/............
Resolving dependencies...
Writing lockfile to /Users/tambara/F1_lap_analysis/lit-taiga-21087/Gemfile.lock

Gemfile.lockをコミットして、再ビルド

> git push
Enumerating objects: 19, done.
Counting objects: 100% (19/19), done.
Delta compression using up to 8 threads
Compressing objects: 100% (13/13), done.
Writing objects: 100% (14/14), 1.66 KiB | 1.66 MiB/s, done.
Total 14 (delta 8), reused 0 (delta 0), pack-reused 0
remote: Compressing source files... done.
remote: Building source:
remote: 
remote: -----> Building on the Heroku-22 stack
remote: -----> Using buildpack: heroku/ruby
remote: -----> Ruby app detected
remote: -----> Installing bundler 2.3.25
remote: -----> Removing BUNDLED WITH version in the Gemfile.lock
remote: -----> Compiling Ruby/Rack
remote: -----> Using Ruby version: ruby-3.1.3
remote:        Purging Cache. Changing stack from heroku-18 to heroku-22
remote: -----> Installing dependencies using bundler 2.3.25
remote:        Running: BUNDLE_WITHOUT='development:test' BUNDLE_PATH=vendor/bundle BUNDLE_BIN=vendor/bundle/bin BUNDLE_DEPLOYMENT=1 bundle install -j4
remote:        Fetching https://github.com/sinatra/sinatra.git
remote:        Fetching gem metadata from https://rubygems.org/............
remote:        Fetching rake 13.0.6
remote:        Installing rake 13.0.6
remote:        Using bundler 2.3.26
remote:        Fetching hashery 2.1.2
remote:        Fetching Ascii85 1.1.0
remote:        Fetching afm 0.2.2
remote:        Fetching multi_json 1.15.0
remote:        Installing Ascii85 1.1.0
remote:        Installing hashery 2.1.2
remote:        Installing multi_json 1.15.0
remote:        Using ruby2_keywords 0.0.5
remote:        Fetching ruby-rc4 0.1.5
remote:        Installing afm 0.2.2
remote:        Fetching ttfunk 1.7.0
remote:        Installing ruby-rc4 0.1.5
remote:        Fetching rack 2.2.6.2
remote:        Fetching tilt 2.1.0
remote:        Installing ttfunk 1.7.0
remote:        Fetching mustermann 3.0.0
remote:        Installing mustermann 3.0.0
remote:        Installing tilt 2.1.0
remote:        Installing rack 2.2.6.2
remote:        Fetching pdf-reader 2.11.0
remote:        Using rack-protection 3.0.5 from https://github.com/sinatra/sinatra.git (at master@4fc73c3)
remote:        Using sinatra 3.0.5 from https://github.com/sinatra/sinatra.git (at master@4fc73c3)
remote:        Fetching sinatra-contrib 3.0.5
remote:        Installing pdf-reader 2.11.0
remote:        Installing sinatra-contrib 3.0.5
remote:        Bundle complete! 9 Gemfile dependencies, 16 gems now installed.
remote:        Gems in the groups 'development' and 'test' were not installed.
remote:        Bundled gems are installed into `./vendor/bundle`
remote:        Bundle completed (3.57s)
remote:        Cleaning up the bundler cache.
remote:        Removing bundler (2.3.25)
remote: -----> Detecting rake tasks
remote: 
remote: 
remote: -----> Discovering process types
remote:        Procfile declares types     -> web
remote:        Default types for buildpack -> console, rake
remote: 
remote: -----> Compressing...
remote:        Done: 57.2M
remote: -----> Launching...
remote:        Released v127
remote:        https://lit-taiga-21087.herokuapp.com/ deployed to Heroku
remote: 
remote: Verifying deploy... done.
To https://git.heroku.com/lit-taiga-21087.git
   6cef8e7..515d352  master -> master

とりあえず、これでビルドは通ったっぽい。しかしながらアクセスするとエラー画面がでる。ログを見てみる。

> heroku logs --tail
 (略)
2023-02-28T02:55:40.608799+00:00 heroku[router]: at=error code=H14 desc="No web processes running" method=GET path="/" host=lit-taiga-21087.herokuapp.com request_id=2273cf84-1e3a-48e1-a980-24304729662d fwd="129.41.57.0" dyno= connect= service= status=503 bytes= protocol=https

H14はdynoが起動してないぞということらしい。このコマンドを打てとガイドされているものを素直にやる。

> heroku ps:scale web=1
 ›   Warning: heroku update available from 7.66.4 to 7.68.2.
Scaling dynos... !
 ▸    Item Could not be Updated: The app owner has to subscribe to Eco to scale your dynos. Learn more at https://blog.heroku.com/new-low-cost-plans

金を払えということのようだ。やっとここまでたどり着いた。満を持して、Herokuにクレジットカードを登録して、金を払う。そして再実行。

> heroku ps:scale web=1
 ›   Warning: heroku update available from 7.66.4 to 7.68.2.
Scaling dynos... done, now running web at 1:Eco

これでよさげ。再度、アクセスしてみるがまだエラー。

> heroku logs --tail
(略)
2023-02-28T03:01:54.590932+00:00 app[api]: Scaled to console@0:Eco rake@0:Eco web@1:Eco
2023-02-28T03:01:57.043327+00:00 heroku[web.1]: Starting process with command `bundle exec ruby main.rb -p 7213`
2023-02-28T03:01:58.289070+00:00 app[web.1]: /app/vendor/bundle/ruby/3.1.0/gems/rack-2.2.6.2/lib/rack/handler.rb:45:in `pick': Couldn't find handler for: thin, falcon, puma, HTTP, webrick. (LoadError)
(略)

rackがエラーを出している。ググると、Ruby3.0でwebrickが標準gemじゃなくなったことが原因とのこと。Gemfileにpumaを足して再チャレンジ。

これで復活した。いろいろあったけど、全部だいたいググったら先人がちゃんと記録を残してくれていて、英語をほとんど読むこともなく対応できた。感謝しかない。

ImbaのQuick Startをたしなむ(1)

https://imba.io/start

npx imba createしろとのことなので、する

> npx imba create
✔ Enter a project name or . for current dir … imba-project
✔ Choose a template or find more at https://imba.io/templates › Default
✔ Create Default project named imba-project in ./imba-project? … yes

Created <Default> project named 'imba-project' in ./imba-project

Installing dependencies
npm WARN deprecated sourcemap-codec@1.4.8: Please use @jridgewell/sourcemap-codec instead

added 234 packages, and audited 235 packages in 20s

69 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities

Install the vscode extension for an optimal experience:
  https://marketplace.visualstudio.com/items?itemName=scrimba.vsimba

Join the Imba community on discord for help and friendly discussions:
  https://discord.gg/mkcbkRw

Get started:

  ➜ cd imba-project
  ➜ npm run dev

ふむ

> cd imba-project/
> ls
node_modules/      package-lock.json  package.json       src/
> cat package.json 
───────┬────────────────────────────────────────────────────────────────────────────────────────────────────────────────
       │ File: package.json
───────┼────────────────────────────────────────────────────────────────────────────────────────────────────────────────
   1   │ {
   2   │     "name": "imba-project",
   3   │     "scripts": {
   4   │         "dev": "imba -w src/index.html",
   5   │         "start": "npm run dev",
   6   │         "build": "imba build src/index.html",
   7   │         "preview": "npx http-server dist"
   8   │     },
   9   │     "devDependencies": {
  10   │         "imba": "^2.0.0-alpha.227"
  11   │     }
  12   │ }
───────┴────────────────────────────────────────────────────────────────────────────────────────────────────────────────
> ls src
index.html  main.imba

さて、早速この2ファイルを見てみるわけだけども、最近のお約束としてはVS codeプラグインまで作っておくわけで、VSCで開いてマーケットプレースでImba拡張を入れる。シンタックスハイライトがちゃんと出る。現代のプログラミング言語はここまで出来てなければならない。

さて、実行してみよう。

> npm run dev

> dev
> imba -w src/index.html

cache dir does not exist - create /Users/tambara/study/imba_study/imba-project/node_modules/imba/.imba-cache
ℹ starting to build in /private/var/folders/kn/44qnqkwx1qq1dy9qr4jtfm3c0000gn/T/tmp-74212-dBNL7cXFjX9F
✔ /private/var/folders/kn/44qnqkwx1qq1dy9qr4jtfm3c0000gn/T/tmp-74212-dBNL7cXFjX9F/index.js.map 10.2kb
✔ /private/var/folders/kn/44qnqkwx1qq1dy9qr4jtfm3c0000gn/T/tmp-74212-dBNL7cXFjX9F/index.js 17.4kb
✔ /private/var/folders/kn/44qnqkwx1qq1dy9qr4jtfm3c0000gn/T/tmp-74212-dBNL7cXFjX9F/public/assets/main.DSF2C6TO.js.map 30.0kb
✔ /private/var/folders/kn/44qnqkwx1qq1dy9qr4jtfm3c0000gn/T/tmp-74212-dBNL7cXFjX9F/public/assets/main.DSF2C6TO.js 55.2kb
✔ /private/var/folders/kn/44qnqkwx1qq1dy9qr4jtfm3c0000gn/T/tmp-74212-dBNL7cXFjX9F/public/assets/main.6WRCZDOK.css.map 0.9kb
✔ /private/var/folders/kn/44qnqkwx1qq1dy9qr4jtfm3c0000gn/T/tmp-74212-dBNL7cXFjX9F/public/assets/main.6WRCZDOK.css 2.6kb
✔ /private/var/folders/kn/44qnqkwx1qq1dy9qr4jtfm3c0000gn/T/tmp-74212-dBNL7cXFjX9F/public/assets/index.RWH5L9H6.css 2.6kb
✔ /private/var/folders/kn/44qnqkwx1qq1dy9qr4jtfm3c0000gn/T/tmp-74212-dBNL7cXFjX9F/public/assets/index.RWH5L9H6.css.map 0.8kb
✔ /private/var/folders/kn/44qnqkwx1qq1dy9qr4jtfm3c0000gn/T/tmp-74212-dBNL7cXFjX9F/manifest.json 0.5kb
ℹ built src/index.html in 673ms - 13.57mb
✔ src/index.html: listening on http://127.0.0.1:3000

アクセスしてみよう

動いているのはわかるけど、さっぱりわからない

「Head First Ruby」を読む(1)

ほぼ新入社員といっていい会社の後輩から、「Excelの先生を探しています」と相談された。最近は学生時代にしっかりCSを学んでいたり、趣味でプログラミングをやっている新人君も多いが、彼女はそういうバックグラウンドを持っていないタイプだ。うちの会社ではそういう人材は普通である。実際、ギークばかりを採ってもうちの仕事がはかどるってわけでもないのだ。

2022年になっても、Excelの需要は高い。バグの傾向分析をしたり、プロジェクトのメンバーリストを元に所属会社別の人数を数えたり、いかにも新入社員に回ってきそうな雑用というのはたくさんあるものだ。そういうものはだいたいがみんなExcelを使ってやっている。彼らはプログラミングというのは納品するためのアプリケーションをつくるためにやるもので、その他の日常の細かなことはExcelの関数でやるものだと考えている。どうしようもなくなるとExcel VBAを担ぎ出すが、それを「プログラミング」だとは思っていない。なぜなら、Excel VBAの抽象化されたRangeオブジェクトの操作は、彼らが思っているプログラミングとどうも似ていないからだ。

私は一時期かなりExcel VBAを書いたし(プロジェクトで雑用に使える許可されたプログラミング環境がそれしかない時代があったのだ)、WindowsのCOMは偉大な発明であり、あんな複雑なものがちゃんと動いて使えているのはマイクロソフトが成し遂げた一種の奇跡みたいなものだと思っているので、割と好きでもある。ただ、さすがにベースとなる言語であるVBAで文字列操作をするのは大分泣きそうだし、2022年にはもっとよい言語がたくさんあるのでアレで仕事をするのはだいぶキツい。

そのようなExcel VBAをプログラミングのバックグラウンドがない新入社員が最初のプログラミング環境として学ぶとそれは大混乱をするだろうし、不幸だろうと思う。もうちっと下地をつくってからであれば、Excel VBAのリファレンスも読みやすくなるに違いない。それに、バグの傾向分析をやるならちょっとしたスクリプト言語の方が何倍も楽ちんだ。というわけで、世界で一番学習しやすい言語であるRubyを真面目に教えてみることにした。

Rubyのことなら内部の仕組みまで含めてある程度わかっている自信があるのだが、2022年の新入社員にRubyを学ぶと何に困難を覚えるのかはさっぱりわからない。私が教材を作るよりは、定評のある本を選ぼう。幸い、彼女は英語に不自由しないので(最近の新人君は間違いなく我々より優秀だ)、会社が金を払ってくれているOreilly Safariで読み放題の中から「Head First Ruby」をやってみることにした。「Head First xxx」シリーズは翻訳をいくつか読んだことがあって信頼がおけるブランドだし、Amazonの★も4以上だ。きっと初心者をはじめてのプログラミングの世界に誘ってくれるに違いない。たぶんな。まあ、ちょっと今年はトラブルプロジェクトに巻き込まれていて、教材を作る時間がないんだ。

というわけで、これを週に1章ずつやるぞということにした。これが新人君にとってキツいのかどうかもわからん。やってみながら考える。電子書籍はページ数がないから分量もよくわからないんだなあ。それにしたって、自分も一応読んでおく必要があるので、いまから1章を読む。そして、ハンズアウト部分をやった結果をこの後に貼る。ただ、まあ、1章は見るべきものはなんもないかな(笑)

Get Ruby

> ruby -v
ruby 3.1.2p20 (2022-04-12 revision 4491bb740a) [arm64-darwin21]
> ruby
^Cruby: Interrupt

うん、Rubyインタプリタはちゃんといる。本ではバージョンが2.0.0だ。結構古いぞ。

Use Ruby

> echo 'puts "hello world"' > hello.rb
> cat hello.rb
───────┬────────────────────────────────────────────────────────────────────────────────────────────────────────────────
       │ File: hello.rb
───────┼────────────────────────────────────────────────────────────────────────────────────────────────────────────────
   1   │ puts "hello world"
───────┴────────────────────────────────────────────────────────────────────────────────────────────────────────────────
> ruby hello.rb 
hello world

伝統を重んじている。

Use Ruby - interactively

irbは大事だ。

> irb
irb(main):001:0> 1 + 2
=> 3
irb(main):002:0> "Hello".upcase
=> "HELLO"
irb(main):003:0> exit
> 

Math operations and comparisons

Rubyを電卓として使おう

> irb
irb(main):001:0> 1 + 2
=> 3
irb(main):002:0> 5.4 - 2.2
=> 3.2
irb(main):003:0> 3 * 4
=> 12
irb(main):004:0> 7 / 3.5
=> 2.0
irb(main):005:0> 2 ** 3
=> 8
irb(main):006:0> 4 < 6
=> true
irb(main):007:0> 4 > 6
=> false
irb(main):008:0> 2 + 2 == 5
=> false

Strings

文字列だ。

irb(main):009:0> "Hello"
=> "Hello"
irb(main):010:0> 'world'
=> "world"

Variables

+=はいきなり理解出来るものだろうか・・・?

irb(main):011:0> small = 8
=> 8
irb(main):012:0> medium = 12
=> 12
irb(main):014:0> small + medium
=> 20
irb(main):015:0> pie = "Lemon"
=> "Lemon"
irb(main):016:0> pie = 3.14
=> 3.14
irb(main):017:0> number = 3
=> 3
irb(main):018:0> number += 1
=> 4
irb(main):019:0> number
=> 4
irb(main):020:0> string = "ab"
=> "ab"
irb(main):021:0> string += "cd"
=> "abcd"
irb(main):022:0> string
=> "abcd"

Everything is an object!

Rubyを最初に学ぶと「すべてがオブジェクト!」と言われても、驚きがあるわけでもないよね

irb(main):023:0> "Hello".upcase
=> "HELLO"
irb(main):024:0> "Hello".reverse
=> "olleH"
irb(main):025:0> 42.even?
=> true
irb(main):026:0> -32.abs
=> 32

Calling a method on an object

EXERCISEがある。やっとこう

irb(main):001:0> 42 / 6
=> 7
irb(main):002:0> 5 > 4
=> true
irb(main):003:0> name = "Zaphod"
=> "Zaphod"
irb(main):004:0> number = -32
=> -32
irb(main):005:0> name.upcase
=> "ZAPHOD"
irb(main):006:0> number.abs
=> 32
irb(main):007:0> "Zaphod".upcase
=> "ZAPHOD"
irb(main):008:0> -32.abs
=> 32
irb(main):009:0> name.reverse
=> "dohpaZ"
irb(main):010:0> number += 10
=> -22
irb(main):011:0> name.upcase.reverse
=> "DOHPAZ"
irb(main):012:0> rand(25)
=> 0
irb(main):013:0> rand(25)
=> 9
irb(main):014:0> rand(25)
=> 6
irb(main):015:0> name.class
=> String
irb(main):016:0> number.class
=> Integer
irb(main):017:0> name * 3
=> "ZaphodZaphodZaphod"

これだけでも語るべきことはいくつかある気がする。

Rubyではほとんどすべてがメソッド呼び出しだ。

irb(main):018:0> 42./(6)
=> 7

変数への代入は違うけど。

irb(main):019:0> number.=(-32)
/Users/tambara/.rbenv/versions/3.1.2/lib/ruby/3.1.0/irb/workspace.rb:119:in `eval': (irb):19: syntax error, unexpected '=' (SyntaxError)                                        
number.=(-32)                                           
       ^                                                
        from /Users/tambara/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/irb-1.4.1/exe/irb:11:in `<top (required)>'
        from /Users/tambara/.rbenv/versions/3.1.2/bin/irb:25:in `load'
        from /Users/tambara/.rbenv/versions/3.1.2/bin/irb:25:in `<main>'

まあ、難しいことは後で出てくるだろう・・・

Let’s build a game

伝統に則って、数当てゲームを作るようだ。ゲームの仕様を英語で読み取るのが難しいが・・・この8つを満たすプログラムをつくるぞと。

  1. 名前を入力してもらって、挨拶する
  2. 1から100までの数字をランダムで決める
  3. プレイヤーの挑戦回数を記録する。10回で当てなきゃいけない
  4. プレイヤーに数字を入力させる
  5. プレイヤーの入力した数字と正解を比較して、高いとか、低いとか伝える
  6. 一致してたら正解だと伝え、挑戦回数も教える
  7. 挑戦回数を使い果たしたら、正解の番号を教える
  8. 正解するか、挑戦回数を使い果たすまで繰り返す

伝統に則ってるなあ・・・

Running scripts

ここからはスクリプトを書かせる。

# Get My Number Game
# Written by: Tambara

puts "伝統と格式の数当てゲームにようこそ"
print "お名前をどうぞ: "

input = gets

puts "#{input}さん、いらっしゃい"
> ruby get_number.rb 
伝統と格式の数当てゲームにようこそ
お名前をどうぞ: たんばりん
たんばりん
さん、いらっしゃい

いらんところに改行はいったー。chompしておかなければならないな。 まあ、それは後で。

Comment

コメントというものがあるねと。

"puts" and "print"

なんで2つあるのか不思議に思うかもしれない。

そして、なんでputsはレシーバーを取らないのだと書いてある。でもそれは2章でやるそうだ。

Method arguments

メソッドには引数をつけられる。 putsはいくつでも引数をつけられるのだ。

first line
=> nil                                           
irb(main):002:0> puts "second line", "third line", "fourth line"
second line
third line                                                                
fourth line                                                               
=> nil                                    

"gets"

後ろの改行も入っちゃうぜー

hoge
=> "hoge\n"    

Parentheses are optional on method calls

メソッドに括弧つけるか問題

irb(main):004:0> puts("one", "two")
one
two                                              
=> nil                                           
irb(main):005:0> puts "one", "two"
one
two                                              
=> nil                                           
irb(main):006:0> gets
hoge
=> "hoge\n"                                      
irb(main):007:0> gets()
hoge
=> "hoge\n"           

しかし、Rubyistはメソッドが引数を取らない場合には「断固として(adamant)」括弧はつけないのだと書いてある。うむ。

String interpolation

interpolateは「補間」らしいが、日本語にしてもわからない。るりまはこれを「式展開」と呼んでいる。

irb(main):008:0> puts "The answer is #{6 * 7}"
The answer is 42
=> nil             

シングルクォートでくくると展開されない。

irb(main):009:0> puts 'The answer is #{6 * 7}'
The answer is #{6 * 7}
=> nil                   

ここの節のコラムで

  1. 行末のセミコロンとかいらんの?
  2. mainメソッドとかいらんの?

という質問が取り上げられていて、答えは両方、「めんどくさいからいらん」である。うむ。

What’s in that string?

あ、さっき私がひっかかった入力してもらった名前の最後に改行が入ってる問題がここで取り上げられる

Inspecting objects with the “inspect” and “p” methods

pメソッドは私がRuby初心者のときに不思議に思ったものの1つ。なぜなら、当時(まだ20世紀の話だ)出たばっかりのバイブルでpの説明はなかなか出てこないのに、みんなruby-list(Rubyメーリングリスト)では使われまくりだったので。

というわけで、ここでpとセットでinspectも紹介される。良いね。

Escape sequences in strings

そして、pを説明したら、エスケープシーケンスの話もする必要があるということ。構成が考えられてる。 そして、シングルクォートとダブルクオートの文字列の使い分けが説明されている。

Calling “chomp” on the string object

ここでchompの説明がくると。

What methods are available on an object?

呼べるメソッドの確認をしてる。どんなオブジェクトにもmethodsメソッドがある。

「るりま」の場所はここで教えた方がいいかもしれない。

Generating a random number

次はランダムな数を得るところを作る。

# Get My Number Game
# Written by: Tambara

puts "伝統と格式の数当てゲームにようこそ"
print "お名前をどうぞ: "

name = gets.chomp

puts "#{name}さん、いらっしゃい"

puts "---"

puts "1から100までの数字を用意します"
puts "当てられるかなー?"
target = rand(100) + 1

puts "target = #{target}"

実行するとこんな感じ

> ruby get_number.rb
伝統と格式の数当てゲームにようこそ
お名前をどうぞ: だるま
だるまさん、いらっしゃい
---
1から100までの数字を用意します
当てられるかなー?
target = 6

Converting to strings

文字列への変換について

irb(main):001:0> num_guesses = 0
=> 0
irb(main):002:0> remaining_guesses = 10 - num_guesses
=> 10
irb(main):003:0> puts remaining_guesses + " guesses left"
(irb):3:in `+': String can't be coerced into Integer (TypeError)
        from (irb):3:in `<main>'                                        
        from /Users/tambara/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/irb-1.4.1/exe/irb:11:in `<top (required)>'
        from /Users/tambara/.rbenv/versions/3.1.2/bin/irb:25:in `load'  
        from /Users/tambara/.rbenv/versions/3.1.2/bin/irb:25:in `<main>'

エラーメッセージの意味がわかりづらいというのはあるだろうなと思う。これを強制的に変換してしまう言語もあるがRubyはそうしない。

Pythonはどうだっけな。

> python
Python 3.10.6 (main, Aug 14 2022, 16:05:52) [Clang 13.1.6 (clang-1316.0.21.2.5)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> num_guesses = 0
>>> remaining_guesses = 10 - num_guesses
>>> print(remaining_guesses + " guesses left")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'int' and 'str'

しないね。

というわけで、to_sする

irb(main):004:0> puts remaining_guesses.to_s + " guesses left"
10 guesses left
=> nil                

ただし、putsprintは渡したら変換してくれるから、任せたらいいのでは・・・あ、改行が・・・

irb(main):005:0> puts remaining_guesses, " guesses left"
10
 guesses left                                                           
=> nil                                           

こうする方法はある(もちろん2行にわけて書いていい)。

irb(main):009:0> print remaining_guesses; puts " guesses left"
10 guesses left
=> nil  

Ruby makes working with strings easy

つか、式展開つかえやと。違いない

irb(main):010:0> puts "#{remaining_guesses} guesses left"
10 guesses left
=> nil

Converting strings to numbers

入力された文字列を数字にする必要がある。to_i使うだけ。

Conditionals

if文が出てくる。truefalseが出てくる。&&||も出てくる。

というわけで、ここまでのところを含めてコードはどうなったかというとこんな感じと。

# Get My Number Game
# Written by: Tambara

puts "伝統と格式の数当てゲームにようこそ"
print "お名前をどうぞ: "

name = gets.chomp

puts "#{name}さん、いらっしゃい"

puts "---"

puts "1から100までの数字を用意します"
puts "当てられるかなー?"
target = rand(100) + 1

num_guess = 0

guessed_it = false

puts "あなたには、#{10 - num_guess}回のチャンスが残っています"
print "正解だと思う数字をどうぞ: "
guess = gets.to_i

if guess < target
  puts "うーん、あなたの答えは小さすぎるようです"
elsif guess > target
  puts "うーん、あなたの答えは大きすぎるようです"
elsif guess == target
  puts "#{name}さん、大正解!"
  puts "あなたは#{num_guess}回目で正解出来ました"
  guessed_it = true
end

if not guessed_it
  puts "残念。あなたは正解出来ませんでした(答えは#{target}でした)"
end

実行する。まだ1回しか応えられないので、クソゲーである。

> ruby get_number.rb
伝統と格式の数当てゲームにようこそ                  
お名前をどうぞ: あらた                              
あらたさん、いらっしゃい                            
---                                                 
1から100までの数字を用意します                      
当てられるかなー?                                  
あなたには、10回のチャンスが残っています         
正解だと思う数字をどうぞ: 50                     
うーん、あなたの答えは大きすぎるようです
残念。あなたは正解出来ませんでした(答えは42でした)

The opposite of “if” is “unless”

if not guessed_it

はダサいのでunlessの説明。unlessはあんまりほかの言語で見たことがない気がするけど、思っているより頻繁に使う。特にガード節とかで。

Loops

whileの説明。untilも説明してくれるけど、unlessと違ってこっちはまず書かない。

しかし、この例では使うのである。おおお。

というわけで、コードはこうなった。

# Get My Number Game
# Written by: Tambara

puts "伝統と格式の数当てゲームにようこそ"
print "お名前をどうぞ: "

name = gets.chomp

puts "#{name}さん、いらっしゃい"

puts "---"

puts "1から100までの数字を用意します"
puts "当てられるかなー?"
target = rand(100) + 1

num_guesses = 0

guessed_it = false

until num_guesses == 10 || guessed_it
  puts "あなたには、#{10 - num_guesses}回のチャンスが残っています"
  print "正解だと思う数字をどうぞ: "
  guess = gets.to_i

  num_guesses += 1

  if guess < target
    puts "うーん、あなたの答えは小さすぎるようです"
  elsif guess > target
    puts "うーん、あなたの答えは大きすぎるようです"
  elsif guess == target
    puts "#{name}さん、大正解!"
    puts "あなたは#{num_guesses}回目で正解出来ました"
    guessed_it = true
  end
end

unless guessed_it
  puts "残念。あなたは正解出来ませんでした(答えは#{target}でした)"
end

Let’s try running our game!

動かしてみようってことで、この章は終わり。

> ruby get_number.rb
伝統と格式の数当てゲームにようこそ
お名前をどうぞ: たんばりん
たんばりんさん、いらっしゃい
---
1から100までの数字を用意します
当てられるかなー?
あなたには、10回のチャンスが残っています
正解だと思う数字をどうぞ: 50
うーん、あなたの答えは大きすぎるようです
あなたには、9回のチャンスが残っています
正解だと思う数字をどうぞ: 30
うーん、あなたの答えは大きすぎるようです
あなたには、8回のチャンスが残っています
正解だと思う数字をどうぞ: 20
うーん、あなたの答えは小さすぎるようです
あなたには、7回のチャンスが残っています
正解だと思う数字をどうぞ: 25
うーん、あなたの答えは大きすぎるようです
あなたには、6回のチャンスが残っています
正解だと思う数字をどうぞ: 23
うーん、あなたの答えは大きすぎるようです
あなたには、5回のチャンスが残っています
正解だと思う数字をどうぞ: 22
たんばりんさん、大正解!
あなたは6回目で正解出来ました

GitLabのインストールをやってみる

ちょっと事情があって、ローカルのマシンにGitLabを入れる必要が出来た。練習にAWSのEC2にインストールしてみることにする。

まだ、OSに何を使うかは決まってないんだけども、とりあえずGitLabのインストールページの一番上にubuntuがあるので、これでやってみることにする。

ここを見ながらやる

Download and install GitLab | GitLab

EC2にt2.mediumのマシンを作って、

sudo apt-get update
sudo apt-get install -y curl openssh-server ca-certificates tzdata perl

を実行する。その後のpostfixのインストールはスキップする。

次に

curl https://packages.gitlab.com/install/repositories/gitlab/gitlab-ee/script.deb.sh | sudo bash

を実行する。

インストーラーを起動するが、そこに外部からみたURLを与える必要があるらしい。お試しなので全然考えてないが、とりあえず、httpで、かつホスト名だけでアクセスしてみたい。どうせ今はSSH越しにしかアクセスしないだろうし。

とりあえず、ホスト名は変えておこう

sudo vi /etc/hosts
sudo hostnamectl set-hostname gitlabstudy

再起動して、インストーラーを起動してみる。ここで気付く。あれ?これってEnterprise Editionじゃん。Community Editionでいいんだけど・・・。ところが、別にお金を払いたくないという理由でCEを選ぶのなら、EEを入れてお金を払わないで使っていればいいらしい。「オレのマシンにプロプライエタリなコードは一切入って欲しくない!」という人は、CEを入れる事もできるらしい。なるほどね。

Community EditionとEnterprise Editionの違い | GitLab.JP

https://www.gitlab.jp/install/ce-or-ee/

sudo EXTERNAL_URL="http://gitlabstudy" apt-get install gitlab-ee

しかし、これはここを最後に固まってしまう

  * ruby_block[authorize Grafana with GitLab] action run

ググってみるとこんなのがみつかる

Ruby_block[authorize Grafana with GitLab] action run timeouts - Observability - GitLab Forum

最後のコメントに「メモリが足りないとなるんだよね」と書かれている。にわかに信じがたい。試しに、t2.large(メモリ8GB)で試してみると上手くいった。なんと・・・

Notes:
Default admin account has been configured with following details:
Username: root
Password: You didn't opt-in to print initial root password to STDOUT.
Password stored to /etc/gitlab/initial_root_password. This file will be cleaned up in first reconfigure run after 24 hours.

NOTE: Because these credentials might be present in your log files in plain text, it is highly recommended to reset the password following https://docs.gitlab.com/ee/security/reset_user_password.html#reset-your-root-password.

gitlab Reconfigured!

       *.                  *.
      ***                 ***
     *****               *****
    .******             *******
    ********            ********
   ,,,,,,,,,***********,,,,,,,,,
  ,,,,,,,,,,,*********,,,,,,,,,,,
  .,,,,,,,,,,,*******,,,,,,,,,,,,
      ,,,,,,,,,*****,,,,,,,,,.
         ,,,,,,,****,,,,,,
            .,,,***,,,,
                ,*,.
  


     _______ __  __          __
    / ____(_) /_/ /   ____ _/ /_
   / / __/ / __/ /   / __ `/ __ \
  / /_/ / / /_/ /___/ /_/ / /_/ /
  \____/_/\__/_____/\__,_/_.___/
  

Thank you for installing GitLab!
GitLab should be available at http://gitlabstudy

For a comprehensive list of configuration options please see the Omnibus GitLab readme
https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/README.md

Help us improve the installation experience, let us know how we did with a 1 minute survey:
https://gitlab.fra1.qualtrics.com/jfe/form/SV_6kVqZANThUQ1bZb?installation=omnibus&release=14-9

パスワード書いたファイルは24時間で消えると書かれてる。怖い

ubuntu@gitlabstudy:/etc/gitlab$ sudo cat initial_root_password 
# WARNING: This value is valid only in the following conditions
#          1. If provided manually (either via `GITLAB_ROOT_PASSWORD` environment variable or via `gitlab_rails['initial_root_password']` setting in `gitlab.rb`, it was provided before database was seeded for the first time (usually, the first reconfigure run).
#          2. Password hasn't been changed manually, either via UI or via command line.
#
#          If the password shown here doesn't work, you must reset the admin password following https://docs.gitlab.com/ee/security/reset_user_password.html#reset-your-root-password.

Password: 8f70FrnDhG1OOIjmHNjmrZ+anZGCAed7ExhD3Hfvfo8=

# NOTE: This file will be automatically deleted in the first reconfigure run after 24 hours.

自分の/private/etc/hostsにgitlabstudyの行を作って

ssh -L 8080:localhost:80 gitlabstudy

した上で、http://localhsot:8080/にアクセスするとGitLabの画面にアクセス出来る。

「Pythonではじめる機械学習」を読んでみる(2)

前回、いろいろなライブラリをインストールしたりしたんだけども、著者お手製のmglearnっていうのをインストールしてねというところでちょっと面倒くさいなーという気持ちになった。そこで、この本のGitHubページをcloneして、そこのnotebookを使うことにした。自分でやった感が一気になくなるので気持ちはそそらないんだけども、まあ、とりあえずね。

で、そのnotebookである 01-introduction.ipynb を走らせたら、1行目でエラーになるという。まあ、あるあるである。

from preamble import *
%matplotlib inline
---------------------------------------------------------------------------
ModuleNotFoundError                       Traceback (most recent call last)
Input In [1], in <cell line: 1>()
----> 1 from preamble import *
      2 get_ipython().run_line_magic('matplotlib', 'inline')

File ~/study/introduction_to_ml_with_python/preamble.py:5, in <module>
      3 import numpy as np
      4 import matplotlib.pyplot as plt
----> 5 import mglearn
      6 from cycler import cycler
      8 set_matplotlib_formats('pdf', 'png')

File ~/study/introduction_to_ml_with_python/mglearn/__init__.py:1, in <module>
----> 1 from . import plots
      2 from . import tools
      3 from .plots import cm3, cm2

File ~/study/introduction_to_ml_with_python/mglearn/plots.py:2, in <module>
      1 from .plot_linear_svc_regularization import plot_linear_svc_regularization
----> 2 from .plot_interactive_tree import plot_tree_progressive, plot_tree_partition
      3 from .plot_animal_tree import plot_animal_tree
      4 from .plot_rbf_svm_parameters import plot_svm

File ~/study/introduction_to_ml_with_python/mglearn/plot_interactive_tree.py:8, in <module>
      6 from io import StringIO
      7 from sklearn.tree import export_graphviz
----> 8 from imageio import imread
      9 from scipy import ndimage
     10 from sklearn.datasets import make_moons

ModuleNotFoundError: No module named 'imageio'

imageioがないってさ。インストールしてみるかね。

> pip3 install -U imageio
DEPRECATION: Configuring installation scheme with distutils config files is deprecated and will no longer work in the near future. If you are using a Homebrew or Linuxbrew Python, please see discussion at https://github.com/Homebrew/homebrew-core/issues/76621
Collecting imageio
  Downloading imageio-2.16.2-py3-none-any.whl (3.3 MB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 3.3/3.3 MB 14.0 MB/s eta 0:00:00
Requirement already satisfied: numpy>=1.20.0 in /usr/local/lib/python3.9/site-packages (from imageio) (1.22.3)
Requirement already satisfied: pillow>=8.3.2 in /usr/local/lib/python3.9/site-packages (from imageio) (9.1.0)
Installing collected packages: imageio
  DEPRECATION: Configuring installation scheme with distutils config files is deprecated and will no longer work in the near future. If you are using a Homebrew or Linuxbrew Python, please see discussion at https://github.com/Homebrew/homebrew-core/issues/76621
DEPRECATION: Configuring installation scheme with distutils config files is deprecated and will no longer work in the near future. If you are using a Homebrew or Linuxbrew Python, please see discussion at https://github.com/Homebrew/homebrew-core/issues/76621
Successfully installed imageio-2.16.2

入った。もう一度やってみよう。

from preamble import *
%matplotlib inline
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
Input In [2], in <cell line: 1>()
----> 1 from preamble import *
      2 get_ipython().run_line_magic('matplotlib', 'inline')

File ~/study/introduction_to_ml_with_python/preamble.py:16, in <module>
     13 plt.rcParams['lines.linewidth'] = 2
     14 plt.rcParams['legend.numpoints'] = 1
     15 plt.rc('axes', prop_cycle=(
---> 16     cycler('color', mglearn.plot_helpers.cm_cycle.colors) +
     17     cycler('linestyle', ['-', '-', "--", (0, (3, 3)), (0, (1.5, 1.5))])))
     19 np.set_printoptions(precision=3, suppress=True)
     21 pd.set_option("display.max_columns", 8)

AttributeError: module 'mglearn' has no attribute 'plot_helpers'

なんでほわーい。mglearn/prot_helpers.pyはちゃんとあるし。

preamble.pyや、mglearn/__init__.pyを見てみたりしてみたけど、わからん・・・。

ところが、preamble.pyimportコメントアウトして、エラーメッセージが変わることなんかを確認したりして、なんどかnotebookも再起動させたりしているウチに、動くようになった。

どゆこと?

preamble.pyを書き換えて、import直後にprint(dir(mglearn)) してみたら、確かにplot_helpersいるし

['ReBl', '__all__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__', 'cm2', 'cm3', 'datasets', 'discrete_scatter', 'plot_2d_separator', 'plot_agglomerative', 'plot_animal_tree', 'plot_cross_validation', 'plot_dbscan', 'plot_decomposition', 'plot_grid_search', 'plot_helpers', 'plot_improper_preprocessing', 'plot_interactive_tree', 'plot_kmeans', 'plot_knn_classification', 'plot_knn_regression', 'plot_linear_regression', 'plot_linear_svc_regularization', 'plot_metrics', 'plot_nmf', 'plot_nn_graphs', 'plot_pca', 'plot_rbf_svm_parameters', 'plot_ridge', 'plot_scaling', 'plot_tree_nonmonotonous', 'plots', 'tools']

ホント、そういうとこやぞ!

というわけで、Pythonのモジュールの仕組みはさっぱりわからない。だけど、この1章のnotebookはエラーなく実行されたみたい。

さて、一緒に勉強会をやっているメンバーでもmglearnのインストール忘れでエラーになる人はちょいちょいいる。そりゃそうだろうし、なんか入れるのやだなと後回しにしているとひっかかる。

図の1.3でグラフを書いているんだけども、そこでmglearnがパラメータに使われていて、ある人が「抜いても別にプロットはされます」と言っている。ふむ。

これが、cloneしたnotebookそのままでプロットしたグラフ

f:id:Tambourine:20220413172254p:plain

こっちが、cmap=mglearn.cm3を抜いたもの

f:id:Tambourine:20220413172418p:plain

cmapはcolor mapなのかな。探してみる

mglearn/plot_helpers.py

cm3 = ListedColormap(['#0000aa', '#ff2020', '#50ff50'])

ってのがある。これだけだね。

というわけで、本はなにひとつ読み進んでないんだけども、今日のところはここまで。

「Pythonではじめる機械学習」を読んでみる(1)

この本を読んでみようという勉強会にやじうま参加中。途中で挫折予定。この本はhttps://learning.oreilly.comで日本語が読めるのでありがたい

まずは1章

scikit-learnをインストールしろと書いてある。condaで入れとけばいいんじゃね?と書いてあるんだけど、自分のマシンにはcondaはなくて、でもjupyter notebookはある。うーむ・・・どういう状況か覚えてない。

とりあえず、scikit-learn.orgのインストールガイドに従ってpipで入れてみる。

> pip3 install -U scikit-learn
DEPRECATION: Configuring installation scheme with distutils config files is deprecated and will no longer work in the near future. If you are using a Homebrew or Linuxbrew Python, please see discussion at https://github.com/Homebrew/homebrew-core/issues/76621
Collecting scikit-learn
  Downloading scikit_learn-1.0.2-cp39-cp39-macosx_10_13_x86_64.whl (8.0 MB)
     |████████████████████████████████| 8.0 MB 5.2 MB/s            
Collecting scipy>=1.1.0
  Downloading scipy-1.8.0-cp39-cp39-macosx_12_0_universal2.macosx_10_9_x86_64.whl (55.6 MB)
     |████████████████████████████████| 55.6 MB 418 kB/s            
Collecting threadpoolctl>=2.0.0
  Downloading threadpoolctl-3.1.0-py3-none-any.whl (14 kB)
Collecting numpy>=1.14.6
  Downloading numpy-1.22.3-cp39-cp39-macosx_10_14_x86_64.whl (17.6 MB)
     |████████████████████████████████| 17.6 MB 33.2 MB/s            
Collecting joblib>=0.11
  Downloading joblib-1.1.0-py2.py3-none-any.whl (306 kB)
     |████████████████████████████████| 306 kB 6.7 MB/s            
Installing collected packages: numpy, threadpoolctl, scipy, joblib, scikit-learn
  DEPRECATION: Configuring installation scheme with distutils config files is deprecated and will no longer work in the near future. If you are using a Homebrew or Linuxbrew Python, please see discussion at https://github.com/Homebrew/homebrew-core/issues/76621
  DEPRECATION: Configuring installation scheme with distutils config files is deprecated and will no longer work in the near future. If you are using a Homebrew or Linuxbrew Python, please see discussion at https://github.com/Homebrew/homebrew-core/issues/76621
  DEPRECATION: Configuring installation scheme with distutils config files is deprecated and will no longer work in the near future. If you are using a Homebrew or Linuxbrew Python, please see discussion at https://github.com/Homebrew/homebrew-core/issues/76621
  DEPRECATION: Configuring installation scheme with distutils config files is deprecated and will no longer work in the near future. If you are using a Homebrew or Linuxbrew Python, please see discussion at https://github.com/Homebrew/homebrew-core/issues/76621
  DEPRECATION: Configuring installation scheme with distutils config files is deprecated and will no longer work in the near future. If you are using a Homebrew or Linuxbrew Python, please see discussion at https://github.com/Homebrew/homebrew-core/issues/76621
DEPRECATION: Configuring installation scheme with distutils config files is deprecated and will no longer work in the near future. If you are using a Homebrew or Linuxbrew Python, please see discussion at https://github.com/Homebrew/homebrew-core/issues/76621
Successfully installed joblib-1.1.0 numpy-1.22.3 scikit-learn-1.0.2 scipy-1.8.0 threadpoolctl-3.1.0
WARNING: You are using pip version 21.3.1; however, version 22.0.4 is available.
You should consider upgrading via the '/usr/local/opt/python@3.9/bin/python3.9 -m pip install --upgrade pip' command.

なんかめっちゃDEPRECATION出てきて気になるが、いったん置いておく。

1.6節で必要なライブラリが指定されている。pandas入ってなかった(笑)。ちまちまpipで入れる。

f:id:Tambourine:20220406164224p:plain
ライブラリのバージョン

結果、こんな感じ。

様々なものを使っていて、それぞれリンクが示されているので、ここにまとめとく

この後、サンプルデータで一回ししてみるところへ続いていくのだけど、今日はセットアップで力尽きた