[クロス本草稿]未調査の項目


# 未調査の項目

本章は、クロスプラットホーム・デスクトップアプリケーションについて、わたしが使ったことのないテクノロジーについて書いている。
なので、他の章よりさらに現実乖離度が高いと思われる。
個人的な印象であることに留意しつつ、短く留めるよう努力する。


## その他のクロスプラットホームFW

クロスプラットホーム・アプリケーションFWはGTK/Qt/Electronだけではない。
ぱっと思いつくものとして、Java,C#,Unity,SPAがある。(これらがFWであるかはともかく)

### Java
JavaはGUIなデスクトップアプリケーションだけのものではないが。
joel氏が「宇宙人が見様見真似で作ったため味を付け忘れたUI、後に修正されたが」と語っていた奴。
<<joelonsoftware本へのリンク>>
Javaの機能は、クロスプラットホームGUIだけでない。

Javaの悪評について。
Javaが使われている環境ではプログラマの扱いが悪いという話が目につくし、Java自体も酷評されている印象がある。
特に恨みもないので擁護するようなことを書いておくことにする。
COBOLを置き換えて長期利用する安定したシステムにJavaが採用されるのは、エコシステムを含めたJava全体で見ればそのようなメリットがあるということだと思う。
Javaが持つ機能は、GC・VM・中間表現その他、当時から見たらどれも革新的な新テクノロジだったと思う。
Javaはそれらの新テクノロジを一度に商用システムに持ち込み一般化したすごいパイオニアだった。
そしてJavaは、商用化についてパイオニアになった。
同時に、パイオニアが犯すことを避けられないあらゆる失敗を抱え込んだのではないかと思う。
悪いことに、Javaは成功した本物の商用言語製品だった。後方互換性を捨てることはできないことは失敗を修正する機会がなかったことも意味する。
長生きすればするほど、Javaは10年前のよく知られた言語設計の失敗を今もそのまま抱えた言語として、悪評も固めていったのではないかと思う。

と、個人的にJava開発環境を悪く思ってはいないが、前述の通りプログラマには劣悪環境であるという話しか聞かない。
個人開発で採用する理由はないし、Java案件に関わらないで済ますためにも、Javaは使いたくない。

### C#
フォームデザイナとかあってすごく使いやすいJavaのようなものらしい。
Linuxでやるのが面倒くさそうなので採用したことはない。

### Unity
ゲーム用。
Qtと同じくモバイルアプリケーションを守備範囲に含む。
ユリアーモの文字割り当て変換(※)のWebサービスを作っていた時、競合がWebサービスをUnityでラップして、デスクトップアプリケーション版をリリースした。
[自家のWebサービス sisto_converter]( https://github.com/MichinariNukazawa/sisto_converter )
[競合のWebサービス EsperantoToJuliamoWithHTML5]( https://sugurunatsuno.github.io/EsperantoToJuliamoWithHTML5/ )
[競合のアプリケーション EsperantoToJuliamo]( https://twitter.com/fuyunosuguru/status/903929591122636800 )
モバイルやゲーム以外にも、Electronと同じ使い方で同じ範囲をカバーできるらしい。
Unityは言語として、C#とJavaScriptが使える。他にもあった気がする。

個人的には、Qtと同じくモバイルアプリケーションに傾注するであろうという予想とか、プロプライエタリであり無償版は起動時ロゴが出る、3D性能が必要なことはしない等の理由で、マルチプラットフォーム・デスクトップアプリケーションFW選択の際に真っ先に脱落する。


ユリアーモは「ことのはアムリラート」劇中に登場する架空の自然言語。
独自のアルファベットを用いる特徴があり、公式からフォントがリリースされている。
[『ことのはアムリラート』ユリアーモフォント配布 公式URL]( http://sukerasparo.com/sp004/font.html )
このフォントのアルファベットの割り当てが特殊であるため、一般に使われるラテン・アルファベットの割り当てを、公式の独自割り当てに変換するサービスが必要となる。

### Webアプリケーション(SPA等)
デスクトップアプリケーションから主役の座を奪い、現在はモバイルアプリケーションと覇権を争っている奴。
滅茶苦茶雑に言えば、ブラウザがあれば動くので、マルチプラットフォーム性が最強。
現実にはいろいろ面倒なところや弱点があり、決定打とはいえない。(このへん列挙は面倒だし、読者を含め私より詳しい人はいくらでもいるので書かない)

ぱっと作れてぱっと使う、家の外やモバイルで使う、軽いツールを作る場合はWebアプリとして実装することが多い。
前述の、ユリアーモの文字割り当て変換は軽いツールの例。

## 使用していないFWの機能

GTKは機能ヘルパ兼依存ライブラリの数が多く、Qtは分厚く範囲の広いクロスプラットホームレイヤであるためこちらも機能が多い。
Electronはわりと機能の少ない小さなアプリケーションを書いたつもりなので、最低限以上の機能は使わないようにしていた。
そのため、筆者が使用していない機能のほうがずっと多い。
そもそも網羅的な入門書を書くのではなく、本物のアプリケーションを書くためにGTK,Qt,Electronを使っているので、全機能を触っておく必要はない...。
(なので本書はこういう感じです。)

というわけで、使っていない機能の話はしておくべきかと思うので本章を書いた。

### Electron:自動アップデート・クラッシュレポート
githubのリリースページにインストーラを置いておくと勝手に認識して自動アップデートしてくれる、とかだと嬉しかったのだが、そういうわけでもない模様。
そもそもElectronを使って作ったlina_dictoはプラットフォーム毎にインストーラを作るのが面倒でzipでリリースしている。
現在はインストーラ形式での配布はしていないので、自動アップデートの前にインストーラ作成しなければ。

クラッシュレポートはJoel先生のブログ記事を読んでからぜひ実装したい機能で、Electronに搭載されていると聞いたときは狂喜乱舞したのだが、いかんせん作ったアプリケーションのユーザベースが少なすぎてコストに見合う気がしない...。

### Qt:QML
JSでアプリケーションを書くなら普通にブラウザアプリのほうがいいと思う...。

### Qt:Android/iOSのモバイルクロス開発
Androidアプリのリリース経験があるが、[lina_dicto for Android]( https://github.com/MichinariNukazawa/lina_dicto_for_android )はElectronで書いたlina_dictoをWebViewで移植して作ったので、QtのAndroid,iOSクロス開発機能は使用しなかった。
QtのAPIがカバーする範囲はよくわからないが、QtのAPIに無い機能については、プラットフォーム毎にネイティブコードを書くし、そういう書き方ができる、とのこと。
<取り消し線>Qtでモバイル開発していた周囲の人々は、iOS11対応で悲鳴を上げていた。</取り消し線>

### Qt:組み込み
死に体のデスクトップアプリケーションからQtが見つけ出した脱出先。
セットトップボックス等でHTMLが重いような場合を想定しているとのこと。
ターゲットによってはQt自体のクロスビルドから自前でする必要がある。
組み込みQtのサポートは販売ライセンスがデスクトップアプリケーション版と異なるという話が。

### GTK:マークアップ言語によるウィンドウ構造記述
QtはQtCreatorをフォームデザイナとしてポトペタするのが一番簡単であるためそれを使うことになるし、目diffを目patchする羽目にでも陥らない限りはQtのXMLを直接触る必要はない。
ElectronはHTMLを書くしかないので、マークアップを使う使わないという話にそもそもならない。
GTKの場合、QtCreator相当のフォームデザイナがクラッシュするような品質であり、マークアップを直接書くのはドキュメントが整備されていたとしても御免こうむるので、コードで直接UIを構築していた。
今はもう少しマシになっているといいなと思う。Windows版はバイナリ配布が無いかもしれないけれど。

### GTK/Qt:非ネイティブな言語バインディング
バインディング境界でバグが発生したら解決できなさそうだったので、生産性を犠牲にして、GTK,Qtではネイティブ言語なC言語,C++言語をそのまま使う選択をした。
また、バインディングはどうしてもネイティブ言語よりドキュメントの優先度が低く、ユーザが少ないこともあって、情報を集めることが難しい。
既にバインディングを使ってアプリケーションを書いてしまった場合や、公式が本当に一級市民扱いのサポートをしている場合以外には、おすすめしない。


[クロス本草稿]ドキュメント


本文章は、技術書典5にて[project daisy bell]( https://twitter.com/MNukazawa )がリリースする予定の、クロスプラットホーム・デスクトップアプリケーション・GUIフレームワーク・クロスレビュー本(仮)(以下、クロス本)の一部の草稿です。
クロス本は、筆者のGtk/Qt/electronの経験と知見について扱います。具体的な解説書というより技術エッセイです。
本文章には、校正前の文章・記憶により記述し未確認の内容・雑なmarkdown風紀法・張ってないURLリンク、などがあります。



# ドキュメント

公式ドキュメントのメンテナンスレベルは重要である。

最低限、APIマニュアルとクイックスタートマニュアルとサンプルコードが公式で欲しい。
サンプルコードは初心者状態で触るので、最低限の作業で完動するものであって欲しい。

公式ドキュメントとは別に、Stack OverflowのFAQ・有象無象のブログ記事(Qiita含む)・物理書籍等の、非公式な外部ドキュメントの充実度は気になるところである。
外部ドキュメントの充実度は、人気のバロメータでありフレームワークの将来性を測る指標として採用検討の際に気になるところである。
筆者は公式ドキュメントの他に、ブログ記事があればそちらも読む。

Gtk/Qt/Electronすべてにおいて、残念ながら物理書籍は母数が少なく、タイミングに恵まれないこともあり、筆者は今のところ縁がない。
書籍の内容は大抵、網羅性は高いがAPI解説が主で公式ドキュメントの日本語訳のような者が多く、実用に関するEffectiveな内容はまずない。

公式ドキュメントにおいて、「XXXについては書いてない」「XXXができない」と書いてあることはまずないので、そのへんは筆者の体感を書いた。
そういう時の筆者は、悪魔の証明になるが、APIマニュアルのページタイトルあたりを網羅して書いてないことを確認しつつ、Web上で同じ結論に到達した人が居なかったか確認している。

一応再度注意しておくと、以下に指摘している不備は、当時のもので現在は解決しているかもしれないし、そもそも十分探していないから見つかっていないだけかもしれない。
実際、開発と無関係に本書のために調べてみると、見たことのない新しい資料がわりと出てくる...。
(こんな同人誌出して大丈夫なのか筆者...本当に)

## Gtk

[GTK+ 3 Reference Manual]( https://developer.gnome.org/gtk3/ )
Gtk2とGtk3でドキュメントが分かれている。Gtk3はさらにversion毎にページが分けられている。
<<ここにスクリーンショット>> [GtkAlignment Widget]( https://developer.gnome.org/gtk3/3.22/GtkAlignment.html )


Gtk3バージョン内でのAPI変更(追加・削除ほか)はドキュメント中に記載され、必要に応じてURLリンクなどが追加される。

とても不思議なことに、何故か、Gtkのドキュメントを引くためだけのアプリケーションが存在する。
内容はWebから参照できるものと同じである。
<<ここにスクリーンショット>> [GTK-Doc, Devhelp]( https://wiki.gnome.org/Apps/Devhelp )

Devhelpという名前は名前空間汚染的(ex.Surface,Go言語)だと思う。

CSSについて十分なドキュメントは存在しない。(これについての文句はCSSの章で書くはず。)

配布パッケージの作り方については公式ドキュメントがない。
Gtk3自体がライブラリビルドだけでも依存関係の解決はユーザ側でできるという前提だが、実際にはライブラリ間のversion依存が複雑。
Gtk3ライブラリのビルドだけで挫折or満足してしまう可能性が高い...。
[参考:Gtk2-3野良ビルドをしている @niloufarjp 氏のtwitter]( https://twitter.com/niloufarjp )
以前からライブラリ以外に必要なものはあったが、Gtk3からはアイコンキャッシュ等、さらに複雑になった模様。
またGtk3以降もバージョンにより必要なものが微妙に異なるようで、野良の情報を集めてなんとかする必要がある。

### サンプルコード

アプリケーションサンプル集が、gtk-3-examplesというパッケージ名で、集約されたアプリケーションの形式で存在する。
Widgetの使用方法がメイン。
<<ここにスクリーンショット>>

問題点として、サンプルコードを単にコピペしただけでは動作するアプリケーションのコードにならない。
サンプルコードはmain部分が共通化されており、このmain部分が記載されていないため、探してきて補完しないと手元でサンプルコードをビルドしてみることができない。
(手元のGtkバージョンで同サンプルコードが有効か否か確認する等したい派の筆者は困る。)
また、サンプルコードはanjutaが生成するほど本格的でなくエラーチェックを真面目にしているわけでもないわりに、わかりやすく単純に書かれているわけでもなく、微妙に参考にしにくい。

### 外部ドキュメント

Qt,Electronと比べると、GtkについてはWeb上の情報は少ない。

非公式のドキュメントとして、
[GTK+/GNOMEによるGUIアプリケーションプログラミング (菅谷保之著)]( http://wiki.cis.iwate-u.ac.jp/~suzuki/Soft/GUI-Application-Programming-20070430.pdf )
がある。
なぜかWeb上で無償公開されている。
Gtk3になってAPIが多少変更されたが、これが扱っている範囲はGtk2,Gtk3の間であまり違いはないので十分参照できる。
筆者は一時期、USBメモリに開発環境と一緒に入れて持ち歩いていた。
今見ると、
[入門GTK+ (菅谷保之著)]( http://wiki.cis.iwate-u.ac.jp/~wiki/csd/docs/GTK-book-all.pdf )
というものがやはりWeb上に有り、こちらのほうが新しい?(といっても2012年だとのことだが)
CSS化前のドキュメントなのでCSS関連の内容はない。
Web上の断片情報が少ない一方で、これらのドキュメントに、主要なWidgetおよび基本的な機能が網羅されている。

物理書籍は、Gtk2時代の古い書籍しか存在しない。
物理書籍も販売されている「入門GTK+ (菅谷保之著)」を同人誌と言うのは無理がある。
同人誌でGtkを扱っているものを見た覚えがない。だから本書を書いたところもある。

### その他

救いとして、GtkにはMLがあり、疑問点は質問すれば大抵は数日中に回答がある。
[modal dialogに関するML上での質問]( https://mail.gnome.org/archives/gtk-app-devel-list/2017-June/msg00050.html )
さっき自分の質問タイトルでWeb検索したら引っかからなかったので、検索性に難があるのでは?

## Qt

[Qt Documentation]( http://doc.qt.io/qt-5/ )
Qtのversion毎にドキュメントが分かれているが番号が飛び飛びなので、どうやら長期サポート・メジャー変更あたりで区切っている模様。

QtもCSSの詳細なドキュメントは無いが、QtCreatorのフォームデザイナとCSS入力支援があるので多少マシである。

ARMボードへのクロスビルドに関する公式ガイドページとか無いの? (仕事でわりと面倒な目に遭った)

### サンプルコード

Qtのサンプルコード集はWebサイトに存在する。
QtCreatorからもサンプルにアクセスできる。
[List of Qt Examples]( http://doc.qt.io/qt-5/all-examples.html )
サンプル毎のスクリーンショットが用意されていることもあり、GtkのようなWidgetの使用方法というより、用途ごとのアプリケーションサンプルとしての色合いが強いように見える。
これはGUIツールキットとしてのGtkとクロスプラットホームFWとしてのQtの性質を反映しているところもあると思う。
プロジェクトのファイルが一通り揃っており、これはそのままビルドして実行できるプロジェクト一式なので、Gtkのサンプルコードよりも参考にしやすい。

### 外部ドキュメント

Gtkと比較すると、調べたときに扱っているページが多い。

Qtにはインストーラ作成の仕組みが用意されているが、これについての同人誌が出ている。
今見たらAmazonで取扱があった。
「インストーラーで配ろう! (理ろぐ) Kindle版」(URLは長くなってしまうため略)
技術書典などで見る。たぶんいつもの人が出しているのかなという気がする。

Qt4(QtC++)時代のものだが、オライリーから動物本が出ている。
また、Qt5になってからのQtQuick(QML)の物理本が出ている。

### その他

Qtには何故か専用のStack Overflowみたいなサイトがある。普通に検索に引っかかるので意識する必要はない。
筆者は幸い質問が必要になったことがないため、使ったことはない。

## Electron

[Electron Documentation]( https://electronjs.org/docs )

### サンプルコード
そんなものはない。
ドキュメント中にコード断片として存在する。
Gtk,QtよりさらにFWとしての性質が強い(テンプレートに埋め込む的な)性質が強いせい、またGUIサンプルはそのままHTMLページサンプルになってしまうからか。

### 外部ドキュメント

出たばかりなのもあり、わりと新しい情報が多い。
//ただ、良くも悪くもnodejs,npm周りのテクノロジなので、陳腐化も早いかも。

大きなアドバンテージとして、HTML/CSS/JSなのでSPAなどWebページ設計のための膨大な情報がそのままElectronで使える。
(これはよく言われていてその通り。)

物理書籍が出ている。
[Electronではじめるアプリ開発 ~JavaScript/HTML/CSSでデスクトップアプリを作ろう](URLは長くなってしまうので略)
筆者は本書を見つけた時点で、初心者向けのスタートガイドや網羅情報はすでに必要なくなっていたので購入しなかった。
自動アップデートやエラーレポートなどの踏み込んだ内容は書いてなかった。

技術書典などでちらほら見なくもない。

### その他

公式ドキュメントにプラットフォーム毎のBuild Instructionsなんてページがあるけれど、Electronはnpmでバイナリ取得できるのもあって、こういう情報はGtkの方にこそ欲しい...。

[クロス本草稿]開発環境・IDE








本文章は、技術書典5にて[project daisy bell]( https://twitter.com/MNukazawa )がリリースする予定の、クロスプラットホーム・デスクトップアプリケーション・GUIフレームワーク・クロスレビュー本(仮)(以下、クロス本)の一部の草稿です。
クロス本は、筆者のGtk/Qt/electronの経験と知見について扱います。具体的な解説書というより技術エッセイです。
本文章には、校正前の文章・記憶により記述し未確認の内容・雑なmarkdown風紀法・張ってないURLリンク、などがあります。

# 開発環境・IDE

現代的なプログラミング言語やフレームワークには、専用の開発環境が用意されていたり、開発を支援するエディタアドオンが利用されていることが多い。
前者はiOSのXcode、AndroidのAndroidStudio、PythonにはJupitorNotebookがある。後者はVSCodeのc++アドオンなど。
GtkにはAnjuta、QtにはQtCreatorというIDEが用意されており、electronには専用IDEのたぐいはない。

筆者は、Qt以外ではGUIアプリケーション以外でもほぼ全てのコーディングにVimを使っている。
またターミナルによるコマンド操作で開発作業を行うことが多い。

## Gtk

GtkのAnjutaは率直に言って使い物にならない。
Ubuntu14.x-16.xの頃、aptパッケージマネージャから導入したAnjutaが、最初のプロジェクト作成ウィザードを実行中にクラッシュしたことがある。
また、公式によるWindowsバイナリは用意されていない模様。

Anjuta自体は、PyGtk言語バインディングだけでなく、Gtkと関係ない開発も行える汎用IDEを目指しているようだ。
(Java、GnomeShellの拡張、等のプロジェクトが作成できる。eclipseのようなものか。)
Gtk向けの開発支援機能として、GUIによるフォームデザイナ(ポトペタ)機能が用意されている。

ドキュメントの章で書いていると思うが、Gtkユーザの中でもAnjuta使用者は少ないため利用するにあたって参考になる情報もあまりない。
フォームデザイナでWidgetをポトペタした後で、Widgetに求めるプロパティを設定するにはどこを編集すれば良いのかわからない。

2018年現在、今ならさすがに解決されているだろうと思ってUbuntu18.04でAnjutaの動作を確認してみたところ、一番最初のウィザードでgtkのライブラリが足りない旨のエラーが出た。
その後のビルドも `**Error**: You must have `libtool' installed.` などと出て失敗したので、色々と依存関係パッケージが足りていないようである。




デバッガも専用のものはないのでgdbを使用する。
メモリ範囲外アクセスのバグ等でクラッシュする場合など。
ビルド時に-gオプションを忘れないこと。

筆者はAnjutaは使わずに、開発はMakefileを書いてターミナルで実行し、コードはvimで書いている。
Windows向けはUbuntu上でmingwを用いてクロスビルドし、公式がGtk3ライブラリのWindows向けバイナリを提供していないため、非公式なビルドをダウンロードしてGtkアプリケーション開発をしている。
[Windows向けGtk3ライブラリ 非公式配布版]( https://drive.google.com/drive/folders/0BwkefA3JqxdIcGVuNkJfLVFyV2c )
[上記ライブラリを配布している @niloufarjp 氏のtwitter]( https://twitter.com/niloufarjp )
MacOXS版は作ったことがない。

## Qt

GtkのAnjutaが使い物にならないのに対して、QtのQtCreatorは実用的である。

Qt公式によりWindowsおよびLinux版(たしかMacOSXも)のバイナリが提供されている。
QtCreator以外に、VisualStudioでもWindows向けQtアプリケーションが開発可能であるらしい。
ありがちな話として、Ubuntuのパッケージマネージャでインストール可能なQtCreatorは大抵バージョンが古い。

QtCreatorにも汎用IDEを目指す部分はあるようなのだが、基本的には、QtおよびQML、その他のQtの言語バインディングに特化している。
もちろんWidgetのフォームデザイナ機能も用意されている。
GtkよりはWidgetのプロパティ設定も読みやすく設定しやすい。
ある程度ユーザも多いようで、Web上に参考になる情報もある。

QtCreatorのフォームデザイナは、QtCreator向けアドオンで拡張することで、独自定義Widgetを扱えるようになる。
ただし、筆者が以前試した限りでは、このアドオン導入は上手く行かなかった。原因を追求していないので、アドオン側が壊れていたか、単に筆者の手順が悪かっただけかもしれないが。

Ubuntu環境ではQtCreatorを使用してQtC++のプロジェクトをビルドする際に、依存するライブラリの不足で失敗することがあるため、追加パッケージとしてlibglをインストールする必要がある。
(Ubuntuバージョンによってパッケージ名が違うかもしれないので検索でlibgl*-devを探すとよい。)

Ubuntu17付近のIMEがfcitxを使用している環境では、QtCreatorに日本語入力するためにはfcitx-qt5アドオンをソースからビルドしてQtCreatorに導入する必要がある。

QtCreatorをVM上のUbuntuで使用する場合に、OpenGL周りの問題なのかWindowが白塗りとなって内容が表示されない場合がある。
その場合、QtCreatorをターミナルから起動し、起動時オプションでOpenGL周りのオプションを無効にすることで回避できる。

以前はビルドシステムはqmake、自動テストはQTestLibのみだったが、現在はビルドシステムにcmakeや自動テストにgoogletestが選択できるようになった模様。

gdbが組み込まれている。QVectorの範囲外アクセスによる例外などが発生した場合に重宝する。

筆者は公式からWindows向けおよびLinuxのQtCreatorをインストールしてQtアプリケーション開発をしている。
クロスビルドを構築するのは面倒なようなので、配布用バイナリは、Windows/Linuxそれぞれ環境構築してビルドしている。MacOSX版は作ったことがない。
Windows向けはVisualStudio版とMinGW版があり、MinGW版を使用していた。近年、VisualStudio版と統合された模様。

## electron

electronには専用IDEのたぐいは存在しないが、chromiumブラウザ由来の強力な実行時デバッガにより、Gtk/Qtとは段違いに高レベルが高いランタイムな開発支援が受けられる。

electronは専用のフォームデザイナは無い。
electronの画面は普通のHTMLなので、ポトペタがしたければ別途HTMLエディタ的なものを探せばよい。(使ったことがないのでどのようなものがあるかは不明)

だが、chromium由来の機能として、実行中に実行時のウィジェットツリー(DOM構造)と、Widgetプロパティを見ることができる。
DOMツリーに追加したelementが、思った箇所に追加されているか、また思い通りに表示されているかを実際の描画で確認することができる。
Windowサイズ変更した際の、Widgetサイズがどのように変化するかも確認できる。
また、CSSの値も確認することができる。
elementのCSSの値は、親elementからの継承、CSSクラス指定による上書き、style Attributeによる直接指定、jsによる書き換えによって複雑に上書き変化するため、思い通りに表示されない場合、人間が追いかけることは大変むずかしい。
思い通りの表示になっていなければ、動作中にDOMツリーやCSSを書き換えながら、思い通りの表示をする方法を探すことができる。
これらのフォームデザイン補助機能は、圧倒的に便利である。
CSSの章でも書くと思うが、electronの実行時GUIビジュアルデバッガを体験すると、GtkとQtのフォームのデバッガビリティの低さは論外であると理解できるし、特にGtkのCSS採用はあまりに愚かな判断ミスだったとしか思えなくなる。
(※このへんの内容は、もっと詳細にしてCSSの章に移動すると思う)

jsのデバッガが組み込まれている。
gdb,QtCreatorなどと同じく、ブレークポイントや関数呼び出しのトレースなどデバッグに必要な操作が行える。

Gtk,Qtとの違いとして、配布の際もchromiumの全機能が付いたままであるため、デバッガを切り離すことはできない。
ユーザからのデバッガへのアクセスを避けたい場合、デバッガの呼び出しショートカットを無効化すること等で対応する。



筆者はnodejsの最新安定版をnodejs公式からインストールして、そのnpmからelectronパッケージおよび他の依存関係パッケージをインストールしてelectronアプリケーション開発をしている。
開発時のtest等のコマンドはpackage.jsonに書くのが一般的なようなのだが、筆者はパッケージ作成まで含めたMakefileを書いている。
コードはhtml,css,jsまですべてvimで書いている。
開発はLinux上で行い、配布用のWindowsおよびMacOSX向けビルドはLinux上で作成できるためそのようにしている。

[クロス本草稿]テスト-Qt

本文章は、技術書典5にて[project daisy bell]( https://twitter.com/MNukazawa )がリリースする予定の、クロスプラットホーム・デスクトップアプリケーション・GUIフレームワーク・クロスレビュー本(仮)(以下、クロス本)の一部の草稿です。
クロス本は、筆者のGtk/Qt/electronの経験について扱った技術エッセイのようなものです。
校正前の文章・記憶により記述し未確認の内容・雑なmarkdown風紀法・張ってないURLリンク、などがあります。


# テスト

本章では各FWにおけるテストの方法について扱う。
GUIアプリケーションの主要なテストには、一般的なユニットテストと、GUIアプリケーション固有のGUIテストのテストの2つがある。
GUIテストにおいては、コールバックイベントをエミュレーションするダミーメッセージの生成と送信、画面更新および描画内容を取得して正解とdiffし結果を確認する方法、という2つの問題がある。

筆者の開発したアプリケーションは、大きなものでも筆者1人が1-2年かけて開発可能な規模のものだった。
そのため、「GUIテストが一覧にされたドキュメント仕様があり、それがすべて自動テスト化されている」というレベルの自動テスト構築は必要ではなかったため、行っていない。
経験は主にユニットテストについてのものであり、GUIテストについては少し書いている。


## Qt

Qtのテストは、なんというか、ほとんどすべてがGtkと逆である。

Qtには、専用のQtTestという名前のテストシステムが用意されている。
QtTestは、ユニットテストとGUIテストの両方をカバーしている。
[Qt Test]( http://doc.qt.io/qt-5/qttest-index.html )
名前空間とインクルードヘッダ名は`QTest`で、qmakeでの追加指定は`QT += testlib`と書く。
また、明記された箇所を見つけることはできなかったが、Qt4までは`QTestLib`と呼ばれ、Qt5以降でQtTestという名前になったのではないかと思う。
[Qt Documentation Archives QTestLib Manual]( http://doc.qt.io/archives/qt-4.8/qtestlib-manual.html )
少々名前が混乱している気がする。Qtの命名ルールに詳しくないので断言はできないが。

テスト専用ではないが、シグナルを監視できる[QSignalSpy Class]( http://doc.qt.io/qt-5/qsignalspy.html )もTestのページに記載されている。
Qtではsignal/slotという名前のメッセージングシステムでGUIを含むイベント処理を行うため、これをQSignalSpyでテストできるという意図なのだろうと想像している。

筆者は結果的に、Qtアプリケーションで自動テストを行わなかった。
そのため経験で語れることはあまりないのだが、ひとつだけ「Qtではgoogletestが使えなかった」というのがある。
当時、Qtアプリでgoogletestが使いたい場合には、Qt公式でない外部のプラグインを導入するなどの工夫が必要があった。
このあたり、Qtがc++風の独自言語により実装されている(※)ため発生した問題かと思っている。
いつからなのかはわからないが、2018年現在、[QtCreaterからgoogletestを選択して使えるようになった模様]( http://doc.qt.io/qtcreator/creator-autotest.html )。
自動テストをしなかったのは、筆者が作ったQtアプリケーションは、QtTestを学ぶかgoogletestを導入するほどの、自動テストの必要性がなかったためである。

※筆者の独自見解。前述の通り(と書いた段階ではまだ「前述」の章を書いていない。書くはず。本当に書くと良いのだが)

[クロス本草稿]テスト-Gtk

本文章は、技術書典5にて[project daisy bell]( https://twitter.com/MNukazawa )がリリースする予定の、クロスプラットホーム・デスクトップアプリケーション・GUIフレームワーク・クロスレビュー本(仮)(以下、クロス本)の一部の草稿です。
クロス本は、筆者のGtk/Qt/electronの経験について扱った技術エッセイのようなものです。
校正前の文章・記憶により記述し未確認の内容・雑なmarkdown風紀法・張ってないURLリンク、などがあります。

# テスト

本章では各FWにおけるテストの方法について扱う。
GUIアプリケーションの主要なテストには、一般的なユニットテストと、GUIアプリケーション固有のGUIテストのテストの2つがある。
GUIテストにおいては、コールバックイベントをエミュレーションするダミーメッセージの生成と送信、画面更新および描画内容を取得して正解とdiffし結果を確認する方法、という2つの問題がある。

## Gtk

Gtkには専用のGUIテスト・ユニットテストのテストフレームワークの類はない。
(無いと思う。使っているときには見あたらなかった。無いよね?)


私がGtkアプリケーションを書く際はC言語で書く。そのため、ユニットテストには[googletest]( https://github.com/google/googletest )を採用している。
C言語以外では書いたことがないのでわからないが、Gtkの各言語バインディングでも、言語ごとのデファクトなユニットテストが問題なく使えると思われる。
これは後述の、QtがC++言語を使用していながらgoogletestと衝突することのほうが、どうかしている。

コールバックイベントエミュレーションは、前述の通りフレームワークが無いので自動化していない。
コールバックテスト化のため、一応の工夫が2つある。
- コールバックエミュレーションのユニットテスト化
- 手動テスト(自動化は諦める)
である。








コールバックエミュレーションのユニットテスト化について。
Gtkコールバックループから来たマウスイベントを機能ブロックに送る前に、必要な情報のみをイベント受け渡し用に用意したstructにコピーしてから渡している。
別にGtkネイティブのstructに必要な変数を代入して使っても良いのだが、実際のイベントの取り回し等も考えて、そのような設計にしている。
実際のコード例を挙げると、vecterionの[et_tool_into機能ブロックのテスト]( https://github.com/MichinariNukazawa/vecterion_vge/blob/master/test/utest/test_et_tool_info.cpp )がある。
読んでらえれば、イベントコールバックをなんとかユニットテスト化しようとしている筆者の苦労の様子がわかる。
et_toolはツール、例えば「マウス操作によるアンカーポイント編集」などの集合である。
アプリケーションウィンドウ上でのマウス操作(EtMouseAction)と現在アクティブなツール種別( et_tool_info_util_func_*_mouse_action()関数 )を受け取り、ドキュメント上のアンカーポイントの編集操作や、ポインタの触れた位置へのフォーカス変更などを行う。

手動テスト(自動化は諦める)について。
個人によるOSSでは手動テスト・リリーステストの類のドキュメントをあまり見かけない印象があるのだが、筆者がOSSをあまり多く読んでいないだけかもしれない。
vecterionには手動による[リリーステスト]( https://github.com/MichinariNukazawa/vecterion_vge/blob/master/test/release_test.md )を用意している。
安定版をリリースする前には、リリーステストを実施することにしている。
目的はちょっとしたうっかりバグによる基本機能欠損状態でのリリースの防止。
リリーステストにより実際に、ポカミスのようなバグを何度か発見している。
リリーステスト自体の前文に書いてあるとおり、省力で済むよう心がけているのだが、それでもこんなに項目が多くなってしまうのだった。
正直、手動テスト自体が苦手なのもあり、あまりやりたくはない。

Gtkのテストについて、未調査の事項として、Gtk製の画像編集アプリケーションであるGimpをビルドした際、テストの段階でメインウィンドウと複数のダイアログが一瞬だけ立ち上がって消える。
何らかの実行テストであると思われるのだが、どのような方法で何をテストしているのかは不明。

## Qt

Qtのテストは、なんというか、ほとんどすべてがGtkと逆である。

(続く)

[クロス本草稿] アプリケーション・アイコン

クロス本 注意書き


本文章は、技術書典5にて[project daisy bell]( https://twitter.com/MNukazawa )がリリースする予定の、クロスプラットホーム・デスクトップアプリケーション・GUIフレームワーク・クロスレビュー本(仮)(以下、クロス本)の一部の草稿です。
校正前の文章・記憶により記述し未確認の内容・雑なmarkdown風紀法・張ってないURLリンク、などがあります。


# アイコン

アプリケーション・アイコンはデスクトップアプリケーションの顔である。
デスクトップアプリケーション固有のデザインテクニック(主に低解像度対応)があった。
モバイルアプリケーションに技術が引き継がれたかはわからない。
アプリケーション・アイコンはプラットフォームOSにより扱いが異なる。
クロスプラットホーム・アプリケーション・フレームワークは、それを吸収したりしていなかったりする。
というかGtk/Qtはともかく、electronだけはわりと吸収しようとしている。

## アイコンデザイン

アイコンの意匠をデザインする際、サイズ毎に固有のデザインをすることが推奨されている。
ドット絵のテクニックとして有名かもしれない。コーポレートデザインでも用途に合わせて微妙にバリエーション違いを用意するという似た技法がある。
ドット数が大きいアイコンではグラデーションなどを用いて意匠を凝らした美麗イラストを使う。
ドット数の少ないものほど要素を省き影や斜め線の少ないデザインにする。
[Microsoftの Windowsデスクトップ アプリケーション アイコンデザインのガイドライン]( https://msdn.microsoft.com/ja-jp/library/windows/desktop/aa511280.aspx )

MacOSが1024x1024pxの巨大アプリケーションアイコンを使用することが一時期有名だった。
現在では、Windows7-10デスクトップでも大きなアイコンが使用される。
Webページのために16x16pxのfaviconアイコンを用意する時代もあったが、モバイルブラウザでは表示されないため事実上不要となった。
2018年の現代において、小サイズアイコンを専用で用意する意味はほぼ無い。

daisy_bellでは、省力化のために、アイコンはサイズフリーなベクタ画像で1種類のみ作成している。
サイズフリーといってもターゲットサイズが無ければデザインの複雑さレベルの方針が立たないので、WindowsとMacOSXの間を取って、512x512pxサイズを基準にしている。

<<ここにlina_dictoのアイコン>>

lina_dictoでは、辞書アプリケーションでは典型的な開いた本の形をベースに、エスペラント語のテーマカラーから塗りを緑色、エスペラント語のシンボルである緑の星を反転した抜きとして使用した。
緑の星に、たぬきの尻尾が生えているのはもちろんすべての元凶たる「ことのはアムリラート」を意識しているため。
ところで、念の為調べてみたところたぬきの尻尾に縞模様があるとは限らないらしいのだが、まあ深く考えることなく縞模様にした。アライグマになってしまったかもしれない。
リリース時はよく出来たアイコンデザインだと自画自賛していたのだが、後にlina_dicto for englishのアイコンをデザインした際に、lina_dictoのアイコンは複雑過ぎたなと思い直して反省している。
サイズフリーデザインにするための工夫として、緑の星などの意匠は小サイズでは印象から消えて、ぱっと見では「緑色の辞書アイコン」に見えるように、サイズを調整している。

<<ここにlina_dicto for englishのアイコン>>
英語版はあくまでlina_dictoのオマケなので、アイコンデザインも検討の時間すら略する勢いで描いた。
青色は個人的な英語のテーマカラーであるため。端を丸めた線で開いた本の形を示して辞書アプリケーションのアイコンとした。
結果的に、「辞書アプリケーション=本の形」というステレオタイプは強力であったために、本家よりもシンプルさで見れば出来が良いアイコンデザインとなってしまった。
不本意な気持ちを感じなくもない。

<<ここにdaisy sequenceのアイコン>>
業務用を意図しているので黒色単色アイコンで大人っぽく(言い方が子供っぽい)。
シーケンス図のlifelineをテーマにしようと決めて、将来的なPlantUML対応を見据えていたのもあって植物っぽい意匠を取り入れようというところまでは考えたのだけれど、具体的にデザインに落とし込むのが大変だった。
一度は捨てようかと思った。
基本のデザインが決まってからも、重なり部分の抜きとか微妙に調整する必要があり、全体的に難産だった。

## アイコンデータの作成

Windows/MacOSXの場合、複数サイズの画像を1ファイルにまとめたアイコンファイルを用意する必要がある。

Windowsではicoファイルを使用する。
icoファイルはGimpで作成できる。
機械的にサイズ違いのレイヤを作ってicoファイル形式でエクスポートするだけなので、自動生成させたいところだったが、Gimpの自動化は自分にはハードルが高かったため手作業で行っている。
GimpにはPython/Schemeによるスクリプト機能はあるのだが、コマンドラインから叩けるかは不明。

Linuxにはアイコンフォーマットがそもそも存在しないので、画像サイズは1種のみで、普通のPNGとかjpgとかを使う。

MacOSXではiconファイルを使用する。
iconファイルはGimpでは作成できない。プロプライエタリなファイルフォーマットなのか、作成するにはMacOSXが必要である。
フリーな実装として<<実装名>>というコマンドラインツールがあるが、私の環境と用途では正しくアイコンファイルが作成されなかった。
(具体的にどううまく行かなかったのかは覚えていない。)
画像ファイルからiconファイルを作成するWebサービスがある。これは機能する。
[ Convert PNG to ICO and ICNS icons online - iConvert Icons ]( https://iconverticons.com/online/ )
以前一度、数日サービスが止まっていたことがあり、管理者へメールを書いたことがある。後日復活した。
このサービスで作成したアイコンは、Ubuntu18.04付近のNautilusファイルビューアのサムネイルでは砂嵐になり、正しく表示されない。だが正しく機能する。
コマンドラインツールで作成した方は、サムネイルでは正しく表示されていたように思う(が、記憶が定かでない)。

### Windows
Windowsにおいて実行ファイルにリソース情報として作者名などを付与することができる。
実行ファイルのアイコンは、リソースの一種である。
MinGWにWindowsターゲットのリソースエディタがあり、Linux上からでもWindows実行ファイルのリソースを操作できる。
(実行ファイル名: `x86_64-w64-mingw32-windres` あたり。)
それを使って実行ファイルにアイコンをリソースとして連結しているものと思われる。

### Linux
Linux実行形式のELFには、Windowsのようにディストリビューション汎用に使えるアイコンリソースの仕様はない模様。
debやrpmは、アイコンを独立した画像ファイルとして持っている。
インストーラによりインストールする際に、環境によりGnomeやKDEのアプリケーション・ランチャに登録するものと思われる。
インストーラがない場合は、ランチャからはアイコンのないアプリケーションとして扱われる。
(Unityデスクトップではデフォルトのアプリケーションアイコンに、デフォルトのアプリケーションアイコンが使用される。警告のような斜め線の入ったアイコンが使用される)
<<ここにUnityデフォルトのアイコン画像のスクショ>>
Ubuntu18.04でlina_dictoを動かした際に、前のバージョンのUbuntuでは問題なかったアプリケーションアイコンが突然認識されなくなり、デフォルトのアプリケーションアイコンになってしまった。
electronのインストーラ作成パッケージ<<の名前>>のバグに近い何かだろうと思ってissueを立てたところ、後日、アプリケーション側で起動時にアイコン画像を指定することが必要になったことが原因だという返答をもらった。
[electron-installer-debian
/application icon broken in ubuntu 18.04 alpha dash area #135]( https://github.com/unindented/electron-installer-debian/issues/135 )
アイコン画像のフォーマットは普通のPNGを使っている。icoファイルなどが使えるのかは必要なかったため確認していない。

### MacOSX
electronのdeployシステムによるMacOSXバイナリへのアイコン付与が、Linux上でも実行できていることから、MacOSXも実行ファイルのどこかにアイコン画像のデータを埋め込むとそれをOSが読んで表示してくれるものらしい。
(他に書くこととくになさそうなので以上)

## アイコンデータの実行ファイルとの結合

### electron
electronではdeplyシステムがWindows/MacOSXの実行ファイルにアイコンの結合を行う。
[パッケージzip作成 electron-packager]( https://github.com/electron-userland/electron-packager )
前述の通り、Linuxのみdeployとは別に、アプリケーション起動時に画像ファイルの指定が必要となる。
[deb作成 electron-installer-debian]( https://github.com/unindented/electron-installer-debian )

[Linux向けのアプリケーションアイコン登録コード例]( https://github.com/MichinariNukazawa/lina_dicto/blob/master/lina_dicto/index.js )
```js
 13 >-------// Create the browser window.¬
 14 >-------win = new BrowserWindow({¬
 15 >------->-------width: 800,¬
 16 >------->-------height: 600,¬
 17 >------->-------icon: 'image/icon.png'¬
 18 >-------})¬
```

### Gtk
アイコンリソース共通化レイヤのような高度なものはない。
ビルドシステムと同じで、Gtk側で独自なものは用意していないので、WindowsではMinGWに頼るなど、プラットフォーム毎になんとかする。

### Qt
Windowsのrc形式リソースファイルを書いてqmakeビルド設定ファイルに登録しておくことで、ビルド時に勝手に結合される。
Qtはアプリケーションのアイコンを扱うつもりはないらしく、この方法も、どちらかというとWindowsリソース情報のオマケ扱いに思える。
Linux、MacOSXではリソースファイルは単に無視される(とドキュメントに書いてあった気がするし、Linuxでは実際そうだった)。

[qmakeファイルでのRCファイル登録マクロの記述例]( http://d.hatena.ne.jp/QtCoder/20110910/1315838284 )
```
win32:RC_FILE = icon_win32.rc
```
[qmake RC_FILE 参照URL]( http://doc.qt.io/archives/qt-5.5/qmake-variable-reference.html#rc-file )

イラストを艦これとアズールレーンに分類する

アジェンダ

nijiflowをベースに、機械学習で艦これとアズールレーンの画像の分類器を作り、学習済みグラフ等を公開した。
また、これのTwitterBotを作成し公開している。
データセットはPixivのタグ付け済み画像情報を元に作成した。
艦これ・アズールレーンそれぞれ6500画像を使用した。
学習は、GPU(google colaboratory)環境にて約48h行い、約10000epocを実行した。
(テストデータによる)認識率は8割を超える。



結果

INFO:tensorflow:Restoring parameters from drive/fleetclassify/checkpoints/fleetclassify_v1_1.0_224_8/model.ckpt-110969

eval/Precision[0.855130792]
eval/Recall[0.86558044]
eval/Accuracy[0.862]
INFO:tensorflow:Finished evaluation at 2018-05-07-12:22:21



TIPS:

- colaboratoryを使いすると規約違反でGPUが使用停止されるのでやめよう
- colaboratoryで大きい学習データをdriveに置いて使うと90分で止まることがある
- MobileNet/nijiflowの学習の再開はコマンドを一行省略でできる

TODO: 

- nijinetの98%(?)から見ると精度がまだ低いように思う
- 学習済みグラフの学習状況をplotするスクリプトが欲しい


艦これとアズールレーンの画像を分類する分類器を作りました。
スクリプトと学習済みグラフを公開しています。
( https://github.com/MichinariNukazawa/daisy_fleetclassify
また、分類器を気軽に試せるように、twitter bot(@DFleetclassify)を公開しています。
(が、簡易なおためし用Botなので専用サーバも立てておらず、不安定かつ不定休です。)

fleetclassifyは nijiflow を元にしています。nijiflow自体は、MobileNetを用いた、転移学習による2D/3Dイラスト判別器です。詳細はリンク先参照。
また、nijiflowの詳細は、SIG2Dにより頒布され、後日公開されるSIG2D Letter1に記載されています。

公開前なのもあって、自分がやった作業についてざっくり書き残しておきます。

fleetclassifyの精度は8割程度で、nijiflowと比べると低いです。(nijiflowはMobileNetを使っていながら98%を実現している。)


# 学習前までの手順

SIG2D Letter1が公開前なので、その前処理までの手順を記載する。
主には、TensorflowのGPU実行環境の作成と、 学習データ作成を行う。

# 環境構築 

```
sudo apt install python3-pip -y
pip3 install tensorflow-gpu
```


# nijiflowの取得

git clone --depth=1 -b niji https://github.com/fallthrough/models


# 学習データ作成

## 学習用画像の収集

pixivより学習データに使用する画像を収集した。
https://github.com/MichinariNukazawa/pixivpy_wrapper

pixivpy_wrapperリポジトリ内の
`kancolle.sh`により`${HOME}/pixiv_data/image__艦これ`が、
`azure.sh`により`${HOME}/pixiv_data/image__アズールレーン`
が作成される。
ディレクトリには、画像ファイルとそのメタデータ`data.json`が作成される。
雑事として、`data.json`は厳密なjsonではないので、読み込みの際に小細工が必要。


## データの前処理

nijiflowは、
`models/research/slim/create_niji_dataset.py`
でTensorFlowの学習データバイナリを生成している。
これは、nijiflow独自(?)の単純なフォーマットの画像一覧テキストファイルを読みこむ。
pixivpy_wrapperのダウンロードデータを、このnijiflowデータファイルに変換する。
これにより、nijiflowの前処理にそのまま乗っかることができる。

変換を行う`util/nijiflow_source_from_path.py`を書いた。
pixivpy_wrapperのダウンロード・ディレクトリから、`data.json`を読んで`nijiflow.list`を作成する。

```
python3 nijiflow_source_from_path.py \
    0 ${HOME}/pixiv_data/image__艦これ         アズールレーン,アズレン
python3 nijiflow_source_from_path.py \
    1 ${HOME}/pixiv_data/image__アズールレーン 艦これ,艦隊これくしょん
```
それぞれの指定ディレクトリ内に`nijiflow.list`が書き出される。

大筋は以下の通り。
- イラスト以外(うごイラ、漫画)の除外
- アズールレーンx艦これの画像の除外
 (艦これアズレンのキャラクターが一枚の絵に入っているような、クロスオーバー的な二次創作イラストを学習から除くため)
-jpg以外の画像の除外
 (pixiv画像にはpngが含まれている。nijiflowがjpgのみ使用していたので、単に除外した)
-(TODO) image.modeがRGBでない画像の除外
 ("L"が20ファイルほど混じっている模様)

ファイルフォーマットは以下の通り。
一行ごとに1つ、ソースファイルの相対パスと分類ID。半角空白(?)で区切るtsvファイルフォーマット。
```tsv:nijiflow.list
68375709_p0.jpg 0
68375681_p0.jpg 0
68375623_p0.jpg 0
68375609_p0.jpg 0
68375495_p0.jpg 0
68375432_p0.jpg 0
```


## 学習データ化

nijiflowのスクリプトを使ってtensorflowの学習データセットを作成する。
データセットは複数のファイルを持ったディレクトリである。
```
python3 models/research/slim/create_niji_dataset.py \
    --output_dir=drive/fleetclassify/fleetclassify_dataset \
    ${HOME}/pixiv_data/image__艦これ/nijiflow.list \
    ${HOME}/pixiv_data/image__アズールレーン/nijiflow.list
```


# 学習の実行

TensorFlow-gpuが、CUDA9.0を要求する。Ubuntu18.04で作業していたのだが、デフォルトのCUDA9.1では駄目とのこと。
(それでCUDAの入れ替えインストール中にUbuntu環境を壊してしまったので)ここから先はgoogle collabにて行った。

ドライバだけ入れないことで回避できるとのこと。
https://medium.com/@taylordenouden/installing-tensorflow-gpu-on-ubuntu-18-04-89a142325138


## チェックポイント(学習済み元モデルデータ)を取得

nijinetの手順に従い、チェックポイントをダウンロードして展開する。
```
mkdir -p drive/fleetclassify/checkpoints/pretrained
pushd drive/fleetclassify/checkpoints/pretrained
wget http://download.tensorflow.org/models/mobilenet_v1_1.0_224_2017_06_14.tar.gz
tar xvzf mobilenet_v1_1.0_224_2017_06_14.tar.gz
popd
```


以上。この後は学習を行う。



# 以下、作業中に出会ったエラーとその解決



# 9:

 複数枚の投稿を取り除く。漫画はともかく、まとめは他作品のキャラも入っているので。ファイルの事前圧縮は、少なくともデータセットのサイズには影響なかった。




####

```
WARNING:tensorflow:From /home/nuka/.local/lib/python3.6/site-packages/tensorflow/contrib/learn/python/learn/datasets/base.py:198: retry (from tensorflow.contrib.learn.python.learn.datasets.base) is deprecated and will be removed in a future version.
Instructions for updating:
Use the retry module or similar alternatives.
WARNING:tensorflow:From train_image_classifier.py:400: create_global_step (from tensorflow.contrib.framework.python.ops.variables) is deprecated and will be removed in a future version.
Instructions for updating:
Please switch to tf.train.create_global_step
Traceback (most recent call last):
  File "train_image_classifier.py", line 576, in <module>
    tf.app.run()
  File "/home/nuka/.local/lib/python3.6/site-packages/tensorflow/python/platform/app.py", line 126, in run
    _sys.exit(main(argv))
  File "train_image_classifier.py", line 406, in main
    FLAGS.dataset_name, FLAGS.dataset_split_name, FLAGS.dataset_dir)
  File "/home/nuka/flow/models/research/slim/datasets/dataset_factory.py", line 59, in get_dataset
    reader)
  File "/home/nuka/flow/models/research/slim/datasets/niji.py", line 85, in get_split
    with open(os.path.join(dataset_dir, 'metadata.json')) as f:
FileNotFoundError: [Errno 2] No such file or directory: '/mnt/tmp/datasets/niji/metadata.json'
```
単なるデータセット引数の指定ミスだった。
`--dataset_dir=${HOME}/flow/nijiflow_data/fleetclassify \`




####

```
InvalidArgumentError (see above for traceback): Cannot assign a device for operation 'gradients/MobilenetV1/Logits/Dropout_1b/dropout/div_grad/BroadcastGradientArgs': Operation was explicitly assigned to /device:GPU:0 but available devices are [ /job:localhost/replica:0/task:0/device:CPU:0 ]. Make sure the device specification refers to a valid device.
     [[Node: gradients/MobilenetV1/Logits/Dropout_1b/dropout/div_grad/BroadcastGradientArgs = BroadcastGradientArgs[T=DT_INT32, _device="/device:GPU:0"](gradients/MobilenetV1/Logits/Dropout_1b/dropout/div_grad/Shape, gradients/MobilenetV1/Logits/Dropout_1b/dropout/div_grad/Shape_1)]]

```
あらかじめGPU学習が設定されていたエラー。GPU版をインストールすることで解決。
`pip3 install --upgrade tensorflow-gpu`

####

```
  File "/usr/lib/python3.6/imp.py", line 343, in load_dynamic
    return _load(spec)
ImportError: libcublas.so.9.0: cannot open shared object file: No such file or directory


Failed to load the native TensorFlow runtime.
```
ローカルのUbuntu18.04環境が原因だった模様。
cuda9.1では駄目で、cuda9.0を入れなければならない、とのことです。
https://developer.nvidia.com/cuda-90-download-archive?target_os=Linux&target_arch=x86_64&target_distro=Ubuntu&target_version=1704&target_type=debnetwork
`sudo apt-get install cuda-9-0 `


####



```
INFO:tensorflow:global step 380: loss = 0.6584 (1.684 sec/step)
INFO:tensorflow:global step 390: loss = 0.6717 (1.288 sec/step)
INFO:tensorflow:global step 400: loss = 0.6621 (2.100 sec/step)
INFO:tensorflow:global step 410: loss = 0.6558 (1.993 sec/step)
INFO:tensorflow:Error reported to Coordinator: <class 'tensorflow.python.framework.errors_impl.DataLossError'>, corrupted record at 78840124
     [[Node: parallel_read/ReaderReadV2_1 = ReaderReadV2[_device="/job:localhost/replica:0/task:0/device:CPU:0"](parallel_read/TFRecordReaderV2_1, parallel_read/filenames)]]
INFO:tensorflow:Finished training! Saving model to disk.
Traceback (most recent call last):
  File "models/research/slim/train_image_classifier.py", line 576, in <module>
    tf.app.run()
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/platform/app.py", line 126, in run
    _sys.exit(main(argv))
  File "models/research/slim/train_image_classifier.py", line 572, in main
    sync_optimizer=optimizer if FLAGS.sync_replicas else None)
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/contrib/slim/python/slim/learning.py", line 784, in train
    ignore_live_threads=ignore_live_threads)
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/training/supervisor.py", line 828, in stop
    ignore_live_threads=ignore_live_threads)
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/training/coordinator.py", line 389, in join
    six.reraise(*self._exc_info_to_raise)
  File "/usr/local/lib/python3.6/dist-packages/six.py", line 693, in reraise
    raise value
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/training/queue_runner_impl.py", line 252, in _run
    enqueue_callable()
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/client/session.py", line 1249, in _single_operation_run
    self._call_tf_sessionrun(None, {}, [], target_list, None)
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/client/session.py", line 1420, in _call_tf_sessionrun
    status, run_metadata)
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/framework/errors_impl.py", line 516, in __exit__
    c_api.TF_GetCode(self.status.status))
tensorflow.python.framework.errors_impl.DataLossError: corrupted record at 78840124
     [[Node: parallel_read/ReaderReadV2_1 = ReaderReadV2[_device="/job:localhost/replica:0/task:0/device:CPU:0"](parallel_read/TFRecordReaderV2_1, parallel_read/filenames)]]
```

```

INFO:tensorflow:Error reported to Coordinator: <class 'tensorflow.python.framework.errors_impl.DataLossError'>, corrupted record at 99555679
     [[Node: parallel_read/ReaderReadV2_1 = ReaderReadV2[_device="/job:localhost/replica:0/task:0/device:CPU:0"](parallel_read/TFRecordReaderV2_1, parallel_read/filenames)]]
INFO:tensorflow:Caught OutOfRangeError. Stopping Training. FIFOQueue '_3_prefetch_queue/fifo_queue' is closed and has insufficient elements (requested 1, current size 0)
     [[Node: fifo_queue_Dequeue = QueueDequeueV2[component_types=[DT_FLOAT, DT_FLOAT], timeout_ms=-1, _device="/job:localhost/replica:0/task:0/device:CPU:0"](prefetch_queue/fifo_queue)]]

Caused by op 'fifo_queue_Dequeue', defined at:
  File "models/research/slim/train_image_classifier.py", line 576, in <module>
    tf.app.run()
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/platform/app.py", line 126, in run
    _sys.exit(main(argv))
  File "models/research/slim/train_image_classifier.py", line 474, in main
    clones = model_deploy.create_clones(deploy_config, clone_fn, [batch_queue])
  File "/content/models/research/slim/deployment/model_deploy.py", line 193, in create_clones
    outputs = model_fn(*args, **kwargs)
  File "models/research/slim/train_image_classifier.py", line 456, in clone_fn
    images, labels = batch_queue.dequeue()
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/ops/data_flow_ops.py", line 440, in dequeue
    self._queue_ref, self._dtypes, name=name)
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/ops/gen_data_flow_ops.py", line 3730, in queue_dequeue_v2
    timeout_ms=timeout_ms, name=name)
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/framework/op_def_library.py", line 787, in _apply_op_helper
    op_def=op_def)
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/framework/ops.py", line 3290, in create_op
    op_def=op_def)
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/framework/ops.py", line 1654, in __init__
    self._traceback = self._graph._extract_stack()  # pylint: disable=protected-access

OutOfRangeError (see above for traceback): FIFOQueue '_3_prefetch_queue/fifo_queue' is closed and has insufficient elements (requested 1, current size 0)
     [[Node: fifo_queue_Dequeue = QueueDequeueV2[component_types=[DT_FLOAT, DT_FLOAT], timeout_ms=-1, _device="/job:localhost/replica:0/task:0/device:CPU:0"](prefetch_queue/fifo_queue)]]

INFO:tensorflow:Finished training! Saving model to disk.
Traceback (most recent call last):
  File "models/research/slim/train_image_classifier.py", line 576, in <module>
    tf.app.run()
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/platform/app.py", line 126, in run
    _sys.exit(main(argv))
  File "models/research/slim/train_image_classifier.py", line 572, in main
    sync_optimizer=optimizer if FLAGS.sync_replicas else None)
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/contrib/slim/python/slim/learning.py", line 784, in train
    ignore_live_threads=ignore_live_threads)
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/training/supervisor.py", line 828, in stop
    ignore_live_threads=ignore_live_threads)
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/training/coordinator.py", line 389, in join
    six.reraise(*self._exc_info_to_raise)
  File "/usr/local/lib/python3.6/dist-packages/six.py", line 693, in reraise
    raise value
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/training/queue_runner_impl.py", line 252, in _run
    enqueue_callable()
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/client/session.py", line 1249, in _single_operation_run
    self._call_tf_sessionrun(None, {}, [], target_list, None)
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/client/session.py", line 1420, in _call_tf_sessionrun
    status, run_metadata)
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/framework/errors_impl.py", line 516, in __exit__
    c_api.TF_GetCode(self.status.status))
tensorflow.python.framework.errors_impl.DataLossError: corrupted record at 99555679
     [[Node: parallel_read/ReaderReadV2_1 = ReaderReadV2[_device="/job:localhost/replica:0/task:0/device:CPU:0"](parallel_read/TFRecordReaderV2_1, parallel_read/filenames)]]

```
テストデータからEXIFの壊れたファイルを除いた。それが原因だったと思われる。
(テストデータ生成部はEXIFが壊れているのをチェック等していない。学習中に使っているのかは不明だが。)

####

```
INFO:tensorflow:Error reported to Coordinator: <class 'tensorflow.python.framework.errors_impl.NotFoundError'>, drive/fleetflow/fleetclassify_dataset/niji_train_00000-of-00100.tfrecord; No such file or directory
     [[Node: parallel_read/ReaderReadV2 = ReaderReadV2[_device="/job:localhost/replica:0/task:0/device:CPU:0"](parallel_read/TFRecordReaderV2, parallel_read/filenames)]]
```
GoogleDriveのファイルが壊れていたのが原因だった。上げ直して解決。




####


```
INFO:tensorflow:Restoring parameters from drive/fleetflow/checkpoints/pretrained/mobilenet_v1_1.0_224.ckpt
2018-04-30 02:46:43.464872: W tensorflow/core/framework/op_kernel.cc:1273] OP_REQUIRES failed at save_restore_v2_ops.cc:184 : Out of range: Read less bytes than requested
Traceback (most recent call last):
  File "models/research/slim/train_image_classifier.py", line 576, in <module>
    tf.app.run()
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/platform/app.py", line 126, in run
    _sys.exit(main(argv))
  File "models/research/slim/train_image_classifier.py", line 572, in main
    sync_optimizer=optimizer if FLAGS.sync_replicas else None)
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/contrib/slim/python/slim/learning.py", line 747, in train
    master, start_standard_services=False, config=session_config) as sess:
  File "/usr/lib/python3.6/contextlib.py", line 83, in __enter__
    raise RuntimeError("generator didn't yield") from None
RuntimeError: generator didn't yield
```
不明。とりあえず再実行中で解決?。



#### google colaboratoryが切れた場合

UbuntuのFireFoxで、ダイアログが出なかったので気づかなかった。
```
INFO:tensorflow:global step 130: loss = 0.6706 (7.589 sec/step)
INFO:tensorflow:global step 140: loss = 0.5755 (2.013 sec/step)
INFO:tensorflow:Saving checkpoint to path drive/fleetflow/checkpoints/fleetclassify_v1_1.0_224_1/model.ckpt
INFO:tensorflow:global_step/sec: 0.233577
INFO:tensorflow:Recording summary at step 141.
2018-04-30 04:03:20.286157: W tensorflow/core/framework/op_kernel.cc:1273] OP_REQUIRES failed at save_restore_v2_ops.cc:134 : Unknown: drive/fleetflow/checkpoints/fleetclassify_v1_1.0_224_1/model.ckpt-140.data-00000-of-00001.tempstate1704126194757243596; Input/output error
INFO:tensorflow:Error reported to Coordinator: <class 'tensorflow.python.framework.errors_impl.UnknownError'>, drive/fleetflow/fleetclassify_dataset/niji_train_00017-of-00100.tfrecord; Input/output error
     [[Node: parallel_read/ReaderReadV2_3 = ReaderReadV2[_device="/job:localhost/replica:0/task:0/device:CPU:0"](parallel_read/TFRecordReaderV2_3, parallel_read/filenames)]]
INFO:tensorflow:global_step/sec: 0.000113881
INFO:tensorflow:Caught OutOfRangeError. Stopping Training. FIFOQueue '_2_prefetch_queue/fifo_queue' is closed and has insufficient elements (requested 1, current size 0)
     [[Node: fifo_queue_Dequeue = QueueDequeueV2[component_types=[DT_FLOAT, DT_FLOAT], timeout_ms=-1, _device="/job:localhost/replica:0/task:0/device:CPU:0"](prefetch_queue/fifo_queue)]]

Caused by op 'fifo_queue_Dequeue', defined at:
  File "models/research/slim/train_image_classifier.py", line 576, in <module>
    tf.app.run()
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/platform/app.py", line 126, in run
    _sys.exit(main(argv))
  File "models/research/slim/train_image_classifier.py", line 474, in main
    clones = model_deploy.create_clones(deploy_config, clone_fn, [batch_queue])
  File "/content/models/research/slim/deployment/model_deploy.py", line 193, in create_clones
    outputs = model_fn(*args, **kwargs)
  File "models/research/slim/train_image_classifier.py", line 456, in clone_fn
    images, labels = batch_queue.dequeue()
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/ops/data_flow_ops.py", line 440, in dequeue
    self._queue_ref, self._dtypes, name=name)
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/ops/gen_data_flow_ops.py", line 3730, in queue_dequeue_v2
    timeout_ms=timeout_ms, name=name)
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/framework/op_def_library.py", line 787, in _apply_op_helper
    op_def=op_def)
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/framework/ops.py", line 3290, in create_op
    op_def=op_def)
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/framework/ops.py", line 1654, in __init__
    self._traceback = self._graph._extract_stack()  # pylint: disable=protected-access

OutOfRangeError (see above for traceback): FIFOQueue '_2_prefetch_queue/fifo_queue' is closed and has insufficient elements (requested 1, current size 0)
     [[Node: fifo_queue_Dequeue = QueueDequeueV2[component_types=[DT_FLOAT, DT_FLOAT], timeout_ms=-1, _device="/job:localhost/replica:0/task:0/device:CPU:0"](prefetch_queue/fifo_queue)]]

INFO:tensorflow:Finished training! Saving model to disk.
2018-04-30 06:24:16.213965: W tensorflow/core/framework/op_kernel.cc:1273] OP_REQUIRES failed at save_restore_v2_ops.cc:109 : Unknown: drive/fleetflow/checkpoints/fleetclassify_v1_1.0_224_1; Input/output error
Traceback (most recent call last):
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/client/session.py", line 1327, in _do_call
    return fn(*args)
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/client/session.py", line 1312, in _run_fn
    options, feed_dict, fetch_list, target_list, run_metadata)
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/client/session.py", line 1420, in _call_tf_sessionrun
    status, run_metadata)
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/framework/errors_impl.py", line 516, in __exit__
    c_api.TF_GetCode(self.status.status))
tensorflow.python.framework.errors_impl.UnknownError: drive/fleetflow/checkpoints/fleetclassify_v1_1.0_224_1; Input/output error
     [[Node: save/SaveV2 = SaveV2[dtypes=[DT_FLOAT, DT_FLOAT, DT_FLOAT, DT_FLOAT, DT_FLOAT, ..., DT_FLOAT, DT_FLOAT, DT_FLOAT, DT_FLOAT, DT_INT64], _device="/job:localhost/replica:0/task:0/device:CPU:0"](_arg_save/Const_0_0, save/SaveV2/tensor_names, save/SaveV2/shape_and_slices, MobilenetV1/Conv2d_0/BatchNorm/beta, MobilenetV1/Conv2d_0/BatchNorm/beta/RMSProp, MobilenetV1/Conv2d_0/BatchNorm/beta/RMSProp_1, MobilenetV1/Conv2d_0/BatchNorm/gamma, MobilenetV1/Conv2d_0/BatchNorm/gamma/RMSProp, MobilenetV1/Conv2d_0/BatchNorm/gamma/RMSProp_1, MobilenetV1/Conv2d_0/BatchNorm/moving_mean, MobilenetV1/Conv2d_0/BatchNorm/moving_variance, MobilenetV1/Conv2d_0/weights, MobilenetV1/Conv2d_0/weights/RMSProp, MobilenetV1/Conv2d_0/weights/RMSProp_1, MobilenetV1/Conv2d_10_depthwise/BatchNorm/beta, MobilenetV1/Conv2d_10_depthwise/BatchNorm/beta/RMSProp, MobilenetV1/Conv2d_10_depthwise/BatchNorm/beta/RMSProp_1,

MobilenetV1/Conv2d_9_pointwise/BatchNorm/gamma/RMSProp, MobilenetV1/Conv2d_9_pointwise/BatchNorm/gamma/RMSProp_1, MobilenetV1/Conv2d_9_pointwise/BatchNorm/moving_mean, MobilenetV1/Conv2d_9_pointwise/BatchNorm/moving_variance, MobilenetV1/Conv2d_9_pointwise/weights, MobilenetV1/Conv2d_9_pointwise/weights/RMSProp, MobilenetV1/Conv2d_9_pointwise/weights/RMSProp_1, MobilenetV1/Logits/Conv2d_1c_1x1/biases, MobilenetV1/Logits/Conv2d_1c_1x1/biases/RMSProp, MobilenetV1/Logits/Conv2d_1c_1x1/biases/RMSProp_1, MobilenetV1/Logits/Conv2d_1c_1x1/weights, MobilenetV1/Logits/Conv2d_1c_1x1/weights/RMSProp, MobilenetV1/Logits/Conv2d_1c_1x1/weights/RMSProp_1, global_step)]]

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/training/supervisor.py", line 990, in managed_session
    yield sess
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/contrib/slim/python/slim/learning.py", line 780, in train
    sv.saver.save(sess, sv.save_path, global_step=sv.global_step)
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/training/saver.py", line 1676, in save
    {self.saver_def.filename_tensor_name: checkpoint_file})
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/client/session.py", line 905, in run
    run_metadata_ptr)
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/client/session.py", line 1140, in _run
    feed_dict_tensor, options, run_metadata)
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/client/session.py", line 1321, in _do_run
    run_metadata)
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/client/session.py", line 1340, in _do_call
    raise type(e)(node_def, op, message)
tensorflow.python.framework.errors_impl.UnknownError: drive/fleetflow/checkpoints/fleetclassify_v1_1.0_224_1; Input/output error
     [[Node: save/SaveV2 = SaveV2[dtypes=[DT_FLOAT, DT_FLOAT, DT_FLOAT, DT_FLOAT, DT_FLOAT, ..., DT_FLOAT, DT_FLOAT, DT_FLOAT, DT_FLOAT, DT_INT64], _device="/job:localhost/replica:0/task:0/device:CPU:0"](_arg_save/Const_0_0, save/SaveV2/tensor_names, save/SaveV2/shape_and_slices, MobilenetV1/Conv2d_0/BatchNorm/beta, MobilenetV1/Conv2d_0/BatchNorm/beta/RMSProp, MobilenetV1/Conv2d_0/BatchNorm/beta/RMSProp_1, MobilenetV1/Conv2d_0/BatchNorm/gamma, MobilenetV1/Conv2d_0/BatchNorm/gamma/RMSProp, MobilenetV1/Conv2d_0/BatchNorm/gamma/RMSProp_1, MobilenetV1/Conv2d_0/BatchNorm/moving_mean, MobilenetV1/Conv2d_0/BatchNorm/moving_variance, MobilenetV1/Conv2d_0/weights, MobilenetV1/Conv2d_0/weights/RMSProp, MobilenetV1/Conv2d_0/weights/RMSProp_1, MobilenetV1/Conv2d_10_depthwise/BatchNorm/beta, MobilenetV1/Conv2d_10_depthwise/BatchNorm/beta/RMSProp, MobilenetV1/Conv2d_10_depthwise/BatchNorm/beta/RMSProp_1, MobilenetV1/Conv2d_10_depthwise/BatchNorm/gamma,

MobilenetV1/Conv2d_9_pointwise/BatchNorm/gamma/RMSProp_1, MobilenetV1/Conv2d_9_pointwise/BatchNorm/moving_mean, MobilenetV1/Conv2d_9_pointwise/BatchNorm/moving_variance, MobilenetV1/Conv2d_9_pointwise/weights, MobilenetV1/Conv2d_9_pointwise/weights/RMSProp, MobilenetV1/Conv2d_9_pointwise/weights/RMSProp_1, MobilenetV1/Logits/Conv2d_1c_1x1/biases, MobilenetV1/Logits/Conv2d_1c_1x1/biases/RMSProp, MobilenetV1/Logits/Conv2d_1c_1x1/biases/RMSProp_1, MobilenetV1/Logits/Conv2d_1c_1x1/weights, MobilenetV1/Logits/Conv2d_1c_1x1/weights/RMSProp, MobilenetV1/Logits/Conv2d_1c_1x1/weights/RMSProp_1, global_step)]]

Caused by op 'save/SaveV2', defined at:
  File "models/research/slim/train_image_classifier.py", line 576, in <module>
    tf.app.run()
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/platform/app.py", line 126, in run
    _sys.exit(main(argv))
  File "models/research/slim/train_image_classifier.py", line 563, in main
    saver=tf.train.Saver(max_to_keep=1000000),
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/training/saver.py", line 1311, in __init__
    self.build()
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/training/saver.py", line 1320, in build
    self._build(self._filename, build_save=True, build_restore=True)
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/training/saver.py", line 1357, in _build
    build_save=build_save, build_restore=build_restore)
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/training/saver.py", line 806, in _build_internal
    save_tensor = self._AddSaveOps(filename_tensor, saveables)
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/training/saver.py", line 326, in _AddSaveOps
    save = self.save_op(filename_tensor, saveables)
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/training/saver.py", line 242, in save_op
    tensors)
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/ops/gen_io_ops.py", line 1680, in save_v2
    shape_and_slices=shape_and_slices, tensors=tensors, name=name)
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/framework/op_def_library.py", line 787, in _apply_op_helper
    op_def=op_def)
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/framework/ops.py", line 3290, in create_op
    op_def=op_def)
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/framework/ops.py", line 1654, in __init__
    self._traceback = self._graph._extract_stack()  # pylint: disable=protected-access

UnknownError (see above for traceback): drive/fleetflow/checkpoints/fleetclassify_v1_1.0_224_1; Input/output error
     [[Node: save/SaveV2 = SaveV2[dtypes=[DT_FLOAT, DT_FLOAT, DT_FLOAT, DT_FLOAT, DT_FLOAT, ..., DT_FLOAT, DT_FLOAT, DT_FLOAT, DT_FLOAT, DT_INT64], _device="/job:localhost/replica:0/task:0/device:CPU:0"](_arg_save/Const_0_0, save/SaveV2/tensor_names, save/SaveV2/shape_and_slices, MobilenetV1/Conv2d_0/BatchNorm/beta, MobilenetV1/Conv2d_0/BatchNorm/beta/RMSProp, MobilenetV1/Conv2d_0/BatchNorm/beta/RMSProp_1, MobilenetV1/Conv2d_0/BatchNorm/gamma, MobilenetV1/Conv2d_0/BatchNorm/gamma/RMSProp, MobilenetV1/Conv2d_0/BatchNorm/gamma/RMSProp_1, MobilenetV1/Conv2d_0/BatchNorm/moving_mean, MobilenetV1/Conv2d_0/BatchNorm/moving_variance, MobilenetV1/Conv2d_0/weights, MobilenetV1/Conv2d_0/weights/RMSProp, MobilenetV1/Conv2d_0/weights/RMSProp_1, MobilenetV1/Conv2d_10_depthwise/BatchNorm/beta, MobilenetV1/Conv2d_10_depthwise/BatchNorm/beta/RMSProp, MobilenetV1/Conv2d_10_depthwise/BatchNorm/beta/RMSProp_1, MobilenetV1/Conv2d_10_depthwise/BatchNorm/gamma, MobilenetV1/Conv2d_10_depthwise/BatchNorm/gamma/RMSProp, MobilenetV1/Conv2d_10_depthwise/BatchNorm/gamma/RMSProp_1,

MobilenetV1/Conv2d_9_pointwise/BatchNorm/gamma/RMSProp, MobilenetV1/Conv2d_9_pointwise/BatchNorm/gamma/RMSProp_1, MobilenetV1/Conv2d_9_pointwise/BatchNorm/moving_mean, MobilenetV1/Conv2d_9_pointwise/BatchNorm/moving_variance, MobilenetV1/Conv2d_9_pointwise/weights, MobilenetV1/Conv2d_9_pointwise/weights/RMSProp, MobilenetV1/Conv2d_9_pointwise/weights/RMSProp_1, MobilenetV1/Logits/Conv2d_1c_1x1/biases, MobilenetV1/Logits/Conv2d_1c_1x1/biases/RMSProp, MobilenetV1/Logits/Conv2d_1c_1x1/biases/RMSProp_1, MobilenetV1/Logits/Conv2d_1c_1x1/weights, MobilenetV1/Logits/Conv2d_1c_1x1/weights/RMSProp, MobilenetV1/Logits/Conv2d_1c_1x1/weights/RMSProp_1, global_step)]]


During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "models/research/slim/train_image_classifier.py", line 576, in <module>
    tf.app.run()
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/platform/app.py", line 126, in run
    _sys.exit(main(argv))
  File "models/research/slim/train_image_classifier.py", line 572, in main
    sync_optimizer=optimizer if FLAGS.sync_replicas else None)
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/contrib/slim/python/slim/learning.py", line 784, in train
    ignore_live_threads=ignore_live_threads)
  File "/usr/lib/python3.6/contextlib.py", line 99, in __exit__
    self.gen.throw(type, value, traceback)
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/training/supervisor.py", line 1000, in managed_session
    self.stop(close_summary_writer=close_summary_writer)
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/training/supervisor.py", line 828, in stop
    ignore_live_threads=ignore_live_threads)
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/training/coordinator.py", line 389, in join
    six.reraise(*self._exc_info_to_raise)
  File "/usr/local/lib/python3.6/dist-packages/six.py", line 693, in reraise

    raise value
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/training/queue_runner_impl.py", line 252, in _run
    enqueue_callable()
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/client/session.py", line 1249, in _single_operation_run
    self._call_tf_sessionrun(None, {}, [], target_list, None)
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/client/session.py", line 1420, in _call_tf_sessionrun
    status, run_metadata)
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/framework/errors_impl.py", line 516, in __exit__
    c_api.TF_GetCode(self.status.status))
tensorflow.python.framework.errors_impl.UnknownError: drive/fleetflow/fleetclassify_dataset/niji_train_00017-of-00100.tfrecord; Input/output error
     [[Node: parallel_read/ReaderReadV2_3 = ReaderReadV2[_device="/job:localhost/replica:0/task:0/device:CPU:0"](parallel_read/TFRecordReaderV2_3, parallel_read/filenames)]]

```


####

```
python3 models/research/slim/train_image_classifier.py --train_dir=drive/fleetclassify/checkpoints/fleetclassify_v1_1.0_224_$(date +'%Y%m%d_%H%M') --dataset_dir=drive/fleetclassify/fleetclassify_dataset --dataset_name=niji --dataset_split_name=train --model_name=mobilenet_v1 --preprocessing_name=mobilenet_v1 --save_interval_secs=600 --save_summaries_secs=600 --checkpoint_path=drive/fleetclassify/checkpoints/pretrained/mobilenet_v1_1.0_224.ckpt --checkpoint_exclude_scopes=MobilenetV1/Logits
python3: Relink `/lib/x86_64-linux-gnu/libudev.so.1' with `/lib/x86_64-linux-gnu/librt.so.1' for IFUNC symbol `clock_gettime'
Segmentation fault (コアダンプ)

```
cuDNNがインストールされていなかったのが原因だった。
https://medium.com/@taylordenouden/installing-tensorflow-gpu-on-ubuntu-18-04-89a142325138


####


```
Traceback (most recent call last):
  File "models/research/slim/export_inference_graph.py", line 59, in <module>
    import tensorflow as tf
ImportError: No module named tensorflow
```

python3をpythonと打っていた(3つけ忘れ)。

以上です。

[クロス本草稿]未調査の項目

# 未調査の項目 本章は、クロスプラットホーム・デスクトップアプリケーションについて、わたしが使ったことのないテクノロジーについて書いている。 なので、他の章よりさらに現実乖離度が高いと思われる。 個人的な印象であることに留意しつつ、短く留めるよう努力する。 ##...