kekeのアトリエ

エンジニア、読書@1915keke

綿矢りさ「蹴りたい背中」が読みたくなる痺れるフレーズ集

自分が2017年読んだ小説の中でトップ3に入るくらい面白かったので紹介します。 「いまさら?」って思うかもしれませんが、大人になってから読むと何倍も楽しめたので、ぜひ皆さんにも読んでみてほしいです。

蹴りたい背中 (河出文庫)

蹴りたい背中 (河出文庫)


綿矢りさとは

Wikepediaによると、綿矢りささんは京都府京都市生まれです。 現在(2017年12月時点)で33歳です。早稲田大学教育学部国語国文科卒業です。

彼女が一躍有名になったのは「インストール」でで第38回文藝賞受賞してからです(当時17歳)。その二年後にこの記事で取り上げる「蹴りたい背中」で芥川賞を受賞して、ミニオンセラーになるなど反響を及びました。

「蹴りたい背中」とは

周りの人間とどうも自分は違う生き物のように感じる主人公が、同級生のオタクであるにな川との交流を沸き立つ、淡い青春を描いています。 この本は、2003年、当時著者が在学中には単行本が刊行されて、第130回芥川龍之介賞を受賞しました。

あらすじ

理科の授業で仲間外れにされたハツは、同じ班のにな川が読んでいる女性ファッション誌のモデル(オリチャン)に目がとまる。ハツは中学生のとき、隣町の無印良品でオリチャンに会ったことがあり、そのことを言うとにな川は興味を持つ。放課後彼の家に呼ばれ、そこでにな川がオリチャンの大ファンであると知る。後日ハツはにな川に頼まれ、オリチャンと会った無印良品へ向かう。そしてにな川の家で休憩する二人だったが、ハツはオリチャンのアイコラ(にな川作)を見つける。ハツは異様な気分になり、にな川を後ろから思い切り蹴り倒す。

その後、にな川が学校を4日間休む。不登校ではないかと言われるも、ハツはにな川の家にお見舞いに行く。実はにな川は徹夜でオリチャンのライブのチケットを取ったため、風邪を引いたのだった。にな川はチケットを4枚買っており、ハツは誰か呼んで一緒に行こうと誘われる。友人は絹代しかいないので、仕方なく絹代を誘って3人でライブに行く。絹代がハツに「にな川はいい彼氏なんじゃないか」「ハツはにな川のことが本当に好きなんだね」と言うが、ハツは「自分の気持ちはそうじゃない」と思っていた。

ライブから帰ると、バスはもう出ていなかった。仕方なくハツと絹代はにな川の家に泊まる。ハツはよく眠れず、ベランダでにな川と話をする。にな川が「オリチャンを一番遠くに感じた」と言ってハツの方を背にして寝転がると、ハツはにな川の背中を蹴ろうとする。指が当たったところでにな川が気づくが、ハツは知らないふりをする。(wikipedia)


読みなるフレーズ

私が勝手ながら、印象だった描写を列挙します。

  • 書き出し

      さびしさは鳴る。耳が痛くなるほど高く澄んだ鈴の音で鳴り響いて、胸を締めつけるから、せめて周りには聞こえないように、 私はプリントを指で千切る。 細長く、細長く。紙を裂く耳障りな音は、孤独の音を消してくれる。気怠げに見せてくれたりもするしね。葉緑体?オオカナダモ?ハッ。っていうこのスタンス。

  • 理科の実験で、自分の椅子が余り物の華奢ないすだった時

    余り者には余り物がしっくりくるのだ。いじめじゃない、ごく自然なことなんだ。

  • はじめてにな川に抱く違和感

    味噌汁の、砂が抜けきっていないアサリを噛みしめて、じゃりっときた時と同じ、ものすごい違和感が一瞬に通り過ぎていく。

  • 友人の友達グループのトランプに誘われて

    どうしてそんなに薄まりたがるんだろう。同じ溶液に使ってぐったり安心して、他人と飽和することは、そんなに心地いいもんなんだろうか。私は余り者も嫌だけど、グループはもっと嫌だ。

  • 陸上の部活動をしているときに思った顧問に対して

    人間に囲まれて先生が舞い上がる度に、生き生きとする度に、私は自分の生き方に対して自信を失っていく。

  • モデルであるオリチャンの雑誌を貪るように読むにな川に対して

    あんなに健康的なものを、よくこれだけ卑猥な目で見られますね。

  • ふと学校で誰にも気にすらされていないことを想って

    学校にいる間は、頭の中ですっと一人でしゃべっているから、外の世界が遠いんだ。

  • 最後ににな川の背中を蹴るハツ

    川の浅瀬に重い石を落とすと、川底の砂が立ち上がって水を濁すように、"あの気持ち"がそこから立ち上がってきて心を濁す。

まとめ

この本の描写は本当に面白くて、読みやすいです。

高校生のときに抱いてた無力感や淡い青春をストレートに描いています。 この冬休みに読んでみてはいかがでしょうか。

最後に好きなフレーズを。

話のネタのために毎日を生きているみたいだった。とにかく"しーん"が怖くて、ボートに浸水してくる冷たい沈黙の水を、つまらない日常の報告で埋めるのに死に物狂いだった。


おすすめの綿矢りさの他の作品

インストール(2001年)

インストール (河出文庫)

インストール (河出文庫)

夢を与える(2006年)

夢を与える (河出文庫)

夢を与える (河出文庫)

かわいそうだね(2012年)

かわいそうだね? (文春文庫)

かわいそうだね? (文春文庫)

誰もがつまづくDjangoをHerokuにデプロイするときあるある

はじめに

今回は「ツナキチ」というニューラルネットワークによる画像認識を用いて人間の顔が一体何% ネコっぽいのかを調べられるWebサイトを作りました。 時間がなくてsafariではデザインが崩れてしまってます。いずれ直します!) 明示的にHerokuでデプロイしていることを示したいので、リンクを貼らさせてもらいます。 https://tunakichi.herokuapp.com/

使ったバージョンは

  • python : v3.6.1
  • django : v1.11.7

です。

コメント、いいね大歓迎です。誤字や間違いは指摘していただけると助かります。

前提

ここではすでにアプリは完成していて、いまからデプロイするぞ!という方を前提にしています。 そしてデプロイをする上で、困ったことを紹介していきます。

デプロイ

pushする

まず、herokuのアプリケーションをherokuに登録しなければなりません。

heroku create <アプリ名>

で登録をすることができます。 一応、うまく繋がっているか確認してください。(これはgitとも接続されているか確認できるので初心者の人は使ってください。)

git remote -v

そして以下のように出ればおっけいです。

hogehoge:~/tunakichi[master]>> git remote -v
heroku  https://git.heroku.com/<リポジトリ名>.git (fetch)
heroku  https://git.heroku.com/<リポジトリ名>.git (push)
origin  git@github.com:KeisukeYamashita/<リポジトリ名>.git (fetch)
origin  git@github.com:KeisukeYamashita/<リポジトリ名>.git (push)

そしたら次にClearDBを作っていきます。簡単にいうとheroku上のDBです。

heroku addons:add cleardb:ignite

そしてherokuの環境変数を変更してください。

heroku config:set DISABLE_COLLECTSTATIC=1

ここでアプリ側の設定を変えなければなりません。wgsi.pyに以下に変更してください。

import os

from dj_static import Cling
from django.core.wsgi import get_wsgi_application

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "<アプリ名>.settings")

application = Cling(get_wsgi_application())

これで設定ができたので、pushすればデプロイできます。

git add .
git commit -m "hogehoge"
git push origin master
git push heroku master

確認

git push heroku masterのときにURLがすでに表示されるのですが、開くには以下のコマンドが便利です。

heroku open

またマイグレーションが必要な方は以下のコマンドでしてください。

heroku run python manege.py migrate

さらにシードデータがあるときはloaddataで入れることができます。 DjangoではJSONによるシードデータを入れる方法と、.YAMLによるシードデータの入れ方があります。

heroku run python manegy.py loaddata <シードデータファイル(JSONorYAML)>

これで再起動すると正しく動くはずです。

heroku restart

トラブルシューティング

[ケース1] herokuへのpushがrejectされるNo default Language

これはDjangoをデプロイしようとしている人の多くが直面する問題です。

原因

ディフォルトでなんの言語を使うのかを指定していないことが問題です。 herokuでは次のような言語がサポートされていて、簡単にいうとどの言語を使いますかという設定をしないといけない。

image.png

今回はPythonを使います。

解決策

まず、pythonのバージョンをruntime.txtに書き込みます。

echo $(python -V) > runtime.txt

次にローカルで使っているパッケージをherokuでも使いたいのでrequirement.txtに記載します。

pip freeze > requirement.txt

そしてpushすればリジェクトされないはずです。

[ケース2]無料枠の落とし穴。「たまに見ると落ちているんですけど、、、」

原因

herokuの無料枠では、30分間アクセスがなれけばスリープモードに入ってしまい、再起動が必要となります。

解決策

毎20分ごとぐらいにherokuに自分でアクセスしてもいいのですが、これを自動化しましょう。 デプロイしたWebサーバー自体が自分にアクセスするように組めばいいのです。

'<アプリ名>/wgsi.pyに以下を追加してください。

import os
import threading
import requests
import time


def awake():
    while True:
        try:
            print("Start Awaking")
            requests.get("http://hogefuga.herokuapp.com/")
            print("End")
        except:
            print("error")
        time.sleep(300)

t = threading.Thread(target=awake)
t.start()

これによって自分にアクセスするようになるので、サーバーがスリープになるようなことはなくなります。

[ケース3]変な名前のモジュールがない。No module name _tkinker

原因

これはグラフを書くのによく使われるmatplotlibライブラリに含まれるmoduleであり、これがherokuでインストールされていないことが原因です。

解決策

まずサーバーにmatplotlibを使うことはおかしいです。笑 (僕はローカルで使っていた数値計算アルゴリズムをそのまま.pyファイルとしてサーバーの計算部分に使おうとしたら勝手に混入していました)

なのでアプリ内の全import <Matploblib>を削除すれば解決できます。

[ケース4]ケース3の一般系。No module name hogehoge

原因

とあるhogehogeモジュールがないといっています。 これは抽象度が高いので、原因がいくつか考えられると思います。

原因1. そんなモジュールなんてない説

本当にそのモジュールがあるかを確認してください。 タイピングミスでmodule名が変わっていないですが?

原因2. herokuにインストールされていない説 ← 定説

ローカルで追加で開発をして、再度pushしたとします。 ローカル環境で新しくpipで導入したことをherokuは知りません。

なのでrequirement.pyを更新することが必要です。

pip freeze > requirement.txt

ScalaでMVCを構築する手順

はじめに

Scalaの超軽量フレームワーク「Scalatra」上でMVC構造を構築するまでを解説します。 Scalatraだけでなく、Scalaは記事が少なすぎる

タグを見るとわかるが、Scalatraに限って8です。

image.png

圧倒的少なさから入門もしにくいし、、、 そのせいで、普段はSwift,Go, Python, Rubyを書きますが、Scalaをやると非常に面白いが文献が少なかった。 なので今回はWebアプリケーション開発できるようにMVCを構築することから始めます。

ニーズ

自分は普段からRailsや、Django、Ginなどの「フルスタックフレームワーク」で開発をしたりしますが、MVC構造といってもあまりにも自由がないです。 Railsなんてブラックボックス化がひどいし、体験的なプログラミングをしてない気がします。

前提

本記事は以下のことを対象にしています。

  • すでにbstなどでビルトが済んでいる方

を対象にしています。

ディレクトリ構造

若干の違いはあるかもしれませんが、以下のようなディレクトリ構造をしているはずです。

src
├── main
│   ├── java
│   ├── resources
│   │   └── logback.xml
│   ├── scala
│   │   ├── ScalatraBootstrap.scala
│   │   └── com
│   │       └── example
│   │           └── app
│   │               └── ScalaServlet.scala
│   └── webapp
│       └── WEB-INF
│           └── web.xml
└── test
    ├── java
    ├── scala
    │   └── com
    │       └── example
    │           └── app
    │               └── MyScalatraServletTests.scala
    └── scala-2.12

初心者な私には、どこに何を配置したらいいのかわからなかったのですが、Goのpackageを思いました。 Packageとは、名前空間と覚えればオッケイ。

つまり、MVCにするならばpackageで区切ればよくて、次の問題はどのように明示的にMVCであることを透明性を保ったまま構築できるかです。

もちろんapp以下に構築するのがいいかもしれません。 先程のディレクトリツリーを抜粋して以下のように変更します。

src
├── main
│   ├── java
│   ├── resources
│   │   └── logback.xml
│   ├── scala
│   │   ├── ScalatraBootstrap.scala
│   │   └── com
│   │       └── example
│   │           └── app
│   │               └── ScalaServlet.scala
│   │               └── view
│   │               └── controller
│   │               └── model
│   └── webapp
│       └── WEB-INF
│           └── web.xml
└── test

ScalaServlet.scalaを中心に、MVCを構築すると透明性の高く、開発しやすいのでおすすめです。

golang+gormで画像をバイナリ化してDBに保存する

はじめに

過去に長期インターンでRubyonRailsをやっていたのでその経験も活かして記事にしました。 はてなブログ記事

やりたいこと

今回は自分のプロフィール(冬仕様)であるこの画像をバイナリ化してDBに保存しようと思います。(184MB)

この記事はRuby on Rails(RoR)を例にしてあげますが、全く理解できなくてもスルーしても読めるようにしたいとは思っています。

今回使用したVersionは以下の通りです。

  • Golang 1.9.1
  • gorm 0.6.3
  • Ruby on Rails 5.0.3(参考用)

より良い記事にしたいので 誤字や間違いがありましたらコメントなどをいただけると幸いです。

方針

Ruby on Railsが、やすやすとここらへんを実装していて、自分も実装経験があるので、参考にしながら進めていきますが Railsはあくまでも比較のためにあるだけなので、さらっと読みたい人はGolang部分だけを見てください。

文法的なことはあまり解説しませんがコンタクトしてくださればわかる範囲で答えます!

実装

DB

この記事では明示的にファイルを示したいのでオブジェクトをFileと名前をつけます。 命名法に違和感を抱く人がいたらすみません。

Railsでは以下のように書いて、ActiveRecord(Ruby製のORM)に働いてもらいます。

class File < ActiveRecord::Migration
  def change
    create_table :files do |t|
      t.binary :upload_file
      t.timestamps
    end
  end
end

なんですがupload_fileがRubyでいうbinaryでDBに書き込まれます。 正直、ORMは仲介人くらいなんでどうでもいいです。要はDBにどんなデータ型で保存されるかが重要なんです。

実際に見てみると(create_atなど省略しています)

Field Type Null Key Default Extra
id int(11) NO PRI NULL auto_increment
upload_file mediumblob YES NULL

となってました。 つまりupload_fileの方はmediumblob(8bit整数)。 これ[]byteと同じ???!!! だってgoでは[]byteと指定するとVARBINARYというデータ型になり、MySQLでは等価だからです。(※厳密には違う) []byteとは[]uint8のaliasです。詳しくは以下リンクで。 https://stackoverflow.com/questions/22950392/difference-between-uint8-byte-golang-slices

では、どのようにしたらbinary fileにできるのでしょうか? ちょっとその前に、これを実装するために、データベースを作るためのdb.goを用意しておきます。

package main

import (
  "os"
  "log"
  "fmt"
  "encoding/binary"
  "image/jpeg"
  "github.com/jinzhu/gorm"
    _ "github.com/jinzhu/gorm/dialects/mysql"
  "bytes"
)

var db *gorm.DB

type File struct {
    gorm.Model
    Source             []byte  
}

func init(){
  db, err = gorm.Open("mysql", "host:hogehoge@mysql/database")
    if err != nil {
        panic(err)
    }
  f = &File{}
  db.CreateTable(f)
  defer db.Close()

これを以下のコマンドで実行し、データベースを作成します。

$ go run db.go

データベース内容

Field Type Null Key Default Extra
id int(11) NO PRI NULL auto_increment
upload_file VARBINARY YES NULL

ImageのBinary化

 最初に

JPEGを画像を扱うためimage/jpegがありますが、この他に標準ではGIF,PNGに対応しています。 この他の拡張子を使う場合は、他にパッケージを使うしかないようです。

Railsでは<form>によってアップロードされたファイルはActionDispatch::Http::UploadedFile クラスなのでReadメソッドで読んでDBに保存すればよかったのですがGolangではどのような感じでしょう。

ディレクトリ構造は以下のようになっています。

.
├── db.go           ← DB作成用
├── image.JPG  ←プロフ画
└── main.go    ← 実行フィアル

以下にコードを示します。 また、最終的なコードはこの記事の最後に書いています。

    file, err := os.Open("image.JPG")
  if err != nil {
        log.Fatal(err)
    }

  img, err := jpeg.Decode(file)
  if err != nil {
      log.Fatal(err)
  }
  file.Close()

  buffer := new(bytes.Buffer)
    if err := jpeg.Encode(buffer, img, nil); err != nil {
        log.Println("unable to encode image.")
    }
  imageBytes := buffer.Bytes()

  f := &File{Source:imageBytes}
  db.Create(u)

解説

それではすこし解説をします。

まず開きたい画像ファイルのパスをPATH部分にいれてos.Open(<PATH>)で開きます。 問題なくいくと*os.File型の戻り値が返ってきます。

    file, err := os.Open("image.JPG")
  if err != nil {
        log.Fatal(err)
  }

次にimage/jpegDecodeメソッドを使ってimage.image型の変数を作ります。 なぜこのimage.image型を作るかというと、あとにエンコーディングをするときに必要だからです。

また、ここで注意したいのはかならずfile.Close()をやってください。

  img, err := jpeg.Decode(file)
  if err != nil {
      log.Fatal(err)
  }
  file.Close()

そしてファイルを生成してください。 同じくout.Close()をすることを忘れないでください。

そしてbytesでバッファを扱うための便利なパッケージがあります。bytes.Bufferは書き込み用のインターフェイスを持っています。 newbyte.Bufferを初期化して、imgがもつimage.image型の変数をともにjpeg.Encodeに渡しています。

  buffer := new(bytes.Buffer)
    if err := jpeg.Encode(buffer, img, nil); err != nil {
        log.Println("unable to encode image.")
    }
  imageBytes := buffer.Bytes()

json.Encodeをなぜこのようにするかというとリファレンスを読んでみたらすぐわかります。

func Encode(w io.Writer, m image.Image, o *Options) error

byte.Bufferは書き込み用のインターフェイスio.Writerを持っているのでわたすことができます。 そして、もとの[]byte型はBytes()で取得できるのでimageBytesに変換することができます。

imageBytes := buffer.Bytes()

そしてこれを構造体に渡してDBに保存して終了です!

f.Source = imageBytes
db.Create(f)
db.Close()

これでこの記事終了です! お疲れ様でした!!

終わりじゃない、、、

というもの、まだ問題が残っています。 それはこのままでは動かないのです。

ERROR 1406 (22001): Data too long for column 'source' at row 1

実は今回のbinaryは長すぎるのです。 というもの、冒頭で、「VARBINARYMIDDLEBLOBは等価だ!Rails通りだぜ!」みたいなことを書きました。

しかし、ここにきて痛い目に合うのです。 データの大きさが鍵となっています。

余談(Blob型の歴史)

もともとMySQLではバイナリ型はblob型で一括してまとめてました。(たしか5.0.7ぐらいまで) しかしバージョンが上がると、VARBINARYVARCHARが出てきました。 MySQL公式ドキュメントから参照しています。

image.png

簡単な乗数の計算ですがだいたいblob型の大きさは

  • TINYBLOB:255B
  • BLOB:65,535B
  • MIDDLEBLOB:16MB
  • LONGBLOB:4GB

であり、VARCHARVARBINARYはというと255Bです。 到底足りません。

解決する

話をもとに戻します。

データのSizeに原因があることがわかりました。 冒頭のこの部分に注目してください。

スクリーンショット 2017-11-19 5.23.45.png

到底足りません!LONGBLOB型が必要です

Railsのときは指摘してなかったじゃないか!と思われるかもしれませんが、その通りで、勝手にデフォルトでなっていました。 Railsに親しい人は当然だと思いますが、実は:limit => 3.gigabyteとして指定してすることで、今回の場合でいうとLongBlobに変更することができるのです。

class File < ActiveRecord::Migration
  def change
    create_table :files do |t|
      t.binary :upload_file, :limit => 3.gigabyte
      t.timestamps
    end
  end
end

同様にgormにだってできます。 gormは構造体をマッピングするという特徴があるので、構造体をいじればどうにかなりそうですよね。 実際もそうで指定したいメンバにgorm:"size:70000などとしてあげるとLONGBlOBに変わります。

type File struct {
    gorm.Model
    Source             []byte    `gorm:"size:70000"`
}

このようにしてSizeを変更できたので最後に実行して終わりです。

$ go run main.go

DBを確認すると人間には優しくない文字列がありますが、それがバイナリです。 最後までお読みしてくださりありがとうございました。 お疲れ様でした。

ソースコード

package main

import (
  "os"
  "log"
  "fmt"
  "image/jpeg"
  "github.com/jinzhu/gorm"
    _ "github.com/jinzhu/gorm/dialects/mysql"
  "bytes"
)

type File struct {
    gorm.Model
    Source []byte `gorm:"size:70000"`
}

func main(){
   db, err := gorm.Open("mysql", "host:hogehoge@mysql/database)
    if err != nil {
        panic(err)
    }
    defer db.Close()

  file, err := os.Open("image.JPG")
  if err != nil {
        log.Fatal(err)
    }

  img, err := jpeg.Decode(file)
  if err != nil {
      log.Fatal(err)
  }
  file.Close()

  buffer := new(bytes.Buffer)
    if err := jpeg.Encode(buffer, img, nil); err != nil {
        log.Println("unable to encode image.")
    }
  imageBytes := buffer.Bytes()

  f := &File{Source:imageBytes}
  db.Create(f)
  db.Close()
}

そしてrunすると実行できます。

go run main.go

余談

最近後輩がこの本を読んでいました。 実際、python以外はプログラミングの本を読んだことがないので、そろそろ読まないとなって思います。

スターティングGo言語

スターティングGo言語

ブログをはじめました

どうも。@1915kekeです。 今日からブログを開始します!

自己紹介

最初に簡単に自己紹介すると

  • Twitterアカウントは@1915kekeです。気軽にフォローしてください。
  • 大学3年生
  • 趣味は読書、プログラミングです。
  • 帰国子女でTOEIC945点もってます。
  • ロボットを毎年作っていました。
  • 夜型です。
  • 好きな食べ物は梅しそです。

最近はキーボード配列を変えて遊んでました。 タイピングゲームは寿司打が最高傑作です。

ブログで取り上げる内容

内容は以下の内容を取り上げていきたいと思います。

  • エンジニアリングに関すること(Go, ruby, Python, 電子工作など)
  • 本について(感想、エッセイなど)
  • 暗号通貨について(Bitcoin, Ethereumなど)

記事に対するコメントは歓迎しますので、ぜひ感想でも、コメントでもください。

泣いてよろこびます。

また、読者になっていただけるとさらに嬉しいです。

これからよろしくお願いします。