yapfの導入

yapfの導入

個人の開発スタイルのような感じですが、Windowsなどでpythonのソースを書いていて、vimへコピー・ペーストをすることがよくあるのですが、何故かインデントのフォーマットが異なってしまうので、そのあとの手間が多いのでなんとかしないと行けないなあと思っていました。(他の言語ならそれほど大きく問題はありませんが、pythonではそういうわけにも行きません。)

そこで、yapfとういうフォーマッタがあることがわかりました。

github.com

googleさん謹製のようです。

yapfのインストール

readmeを見ればわかりますが以下の様にインストールします。

$ pip install yapf
Collecting yapf
  Downloading yapf-0.17.0-py2.py3-none-any.whl (151kB)
    100% |????????????????????????????????| 153kB 1.1MB/s
Installing collected packages: yapf
Successfully installed yapf-0.17.0

raspberrypiでインストールするとyapf~/.local/bin/yapfにインストールされるようです。

実行するとこんな感じになります。

$ ~/.local/bin/yapf --version
yapf 0.17.0

$ ~/.local/bin/yapf --help
usage: yapf [-h] [-v] [-d | -i] [-r | -l START-END] [-e PATTERN]
            [--style STYLE] [--style-help] [--no-local-style] [-p]
            [files [files ...]]

Formatter for Python code.

positional arguments:
  files

optional arguments:
  -h, --help            show this help message and exit
  -v, --version         show version number and exit
  -d, --diff            print the diff for the fixed source
  -i, --in-place        make changes to files in place
  -r, --recursive       run recursively over directories
  -l START-END, --lines START-END
                        range of lines to reformat, one-based
  -e PATTERN, --exclude PATTERN
                        patterns for files to exclude from formatting
  --style STYLE         specify formatting style: either a style name (for
                        example "pep8" or "google"), or the name of a file
                        with style settings. The default is pep8 unless a
                        .style.yapf or setup.cfg file located in one of the
                        parent directories of the source file (or current
                        directory for stdin)
  --style-help          show style settings and exit; this output can be saved
                        to .style.yapf to make your settings permanent
  --no-local-style      don't search for local style definition
  -p, --parallel        Run yapf in parallel when formatting multiple files.
                        Requires concurrent.futures in Python 2.X

テスト

公式サイトのサンプルを使って実験してみます。

github.com

x = {  'a':37,'b':42,

'c':927}

y = 'hello ''world'
z = 'hello '+'world'
a = 'hello {}'.format('world')
class foo  (     object  ):
  def f    (self   ):
    return       37*-+2
  def g(self, x,y=42):
      return y
def f  (   a ) :
  return      37+-+a[42-x :  y**3]

f:id:ueponx:20170910140531p:plain

$ ~/.local/bin/yapf sample.py
Traceback (most recent call last):
  File "/home/pi/.local/bin/yapf", line 11, in <module>
    sys.exit(run_main())
  File "/home/pi/.local/lib/python2.7/site-packages/yapf/__init__.py", line 296, in run_main
    sys.exit(main(sys.argv))
  File "/home/pi/.local/lib/python2.7/site-packages/yapf/__init__.py", line 188, in main
    parallel=args.parallel)
  File "/home/pi/.local/lib/python2.7/site-packages/yapf/__init__.py", line 236, in FormatFiles
    in_place, print_diff, verify)
  File "/home/pi/.local/lib/python2.7/site-packages/yapf/__init__.py", line 259, in _FormatFile
    logger=logging.warning)
  File "/home/pi/.local/lib/python2.7/site-packages/yapf/yapflib/yapf_api.py", line 91, in FormatFile
    verify=verify)
  File "/home/pi/.local/lib/python2.7/site-packages/yapf/yapflib/yapf_api.py", line 129, in FormatCode
    tree = pytree_utils.ParseCodeToTree(unformatted_source)
  File "/home/pi/.local/lib/python2.7/site-packages/yapf/yapflib/pytree_utils.py", line 102, in ParseCodeToTree
    tree = parser_driver.parse_string(code, debug=False)
  File "/usr/lib/python2.7/lib2to3/pgen2/driver.py", line 106, in parse_string
    return self.parse_tokens(tokens, debug)
  File "/usr/lib/python2.7/lib2to3/pgen2/driver.py", line 47, in parse_tokens
    for quintuple in tokens:
  File "/usr/lib/python2.7/lib2to3/pgen2/tokenize.py", line 429, in generate_tokens
    ("<tokenize>", lnum, pos, line))
  File "sample.py", line 11
    def g(self, x,y=42):
    ^
IndentationError: unindent does not match any outer indentation level

動かない…エラーメッセージから察するに、Webページのものをコピペして使うとpythonの文法まで崩れてしまっているようです。

Teratermのウインドウにドラッグ・アンド・ドロップすることで実行できる、scpなどでファイル転送をすると…

$ cat sample.py
x = {  'a':37,'b':42,

'c':927}

y = 'hello ''world'
z = 'hello '+'world'
a = 'hello {}'.format('world')
class foo  (     object  ):
  def f    (self   ):
    return       37*-+2
  def g(self, x,y=42):
      return y
def f  (   a ) :
  return      37+-+a[42-x :  y**3]

$ ~/.local/bin/yapf sample.py
x = {'a': 37, 'b': 42, 'c': 927}

y = 'hello ' 'world'
z = 'hello ' + 'world'
a = 'hello {}'.format('world')


class foo(object):
    def f(self):
        return 37 * -+2

    def g(self, x, y=42):
        return y


def f(a):
    return 37 + -+a[42 - x:y**3]

うまく実行できたようです。ファイルを変換したものに上書きするには-iをつければいいようです。他にも処理後との差分(diff)を表示する-d再帰的に実行する-rのスイッチがあります。

$ ~/.local/bin/yapf -i sample.py
pi@raspberrypi:~/yapf_sample $ cat sample.py
x = {'a': 37, 'b': 42, 'c': 927}

y = 'hello ' 'world'
z = 'hello ' + 'world'
a = 'hello {}'.format('world')


class foo(object):
    def f(self):
        return 37 * -+2

    def g(self, x, y=42):
        return y


def f(a):
    return 37 + -+a[42 - x:y**3]

REPL環境での実行でモジュールとして使用することもできる様です。 githubのページでは以下のようになると書いてあるのですが、

>>> from yapf.yapflib.yapf_api import FormatCode  # reformat a string of code

>>> FormatCode("f ( a = 1, b = 2 )")
'f(a=1, b=2)\n'

自分の環境では

$ python
Python 2.7.13 (default, Jan 19 2017, 14:48:08)
[GCC 6.3.0 20170124] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from yapf.yapflib.yapf_api import FormatCode  # reformat a string of code
>>> FormatCode("f ( a = 1, b = 2 )")
(u'f(a=1, b=2)\n', True)
>>>

となりました。python2だったからかな?念のためpython3でも実行してみました。

$ pip3 install yapf
Collecting yapf
  Using cached yapf-0.17.0-py2.py3-none-any.whl
Installing collected packages: yapf
Successfully installed yapf-0.17.0

$ python3
Python 3.5.3 (default, Jan 19 2017, 14:11:04)
[GCC 6.3.0 20170124] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from yapf.yapflib.yapf_api import FormatCode
>>> FormatCode("f ( a = 1, b = 2 )")
('f(a=1, b=2)\n', True)
>>> FormatCode("def g( ):\n    a=1\n    b = 2\n    return a==b", lines=[(1, 1), (2, 3)])
('def g():\n    a = 1\n    b = 2\n    return a==b\n', True)

ユニコード文字列を指すのuのプリフィックス以外は変わったところが無いみたい、あれ?

終わりに

コピペしてフォーマットが少し崩れるぐらいであれば、なんとかできるかなと思いましたが、派手に崩れる(文法的に崩れるレベル)とちょっとむずかしい様です。

RaspberryPiだけでなくWindowsのanaconda環境にもインストールしましたがこっちで使ったほうがいいのかもしれません。(コピペする前にこっちで整形をするという感じ)

Node.jsでRSSのデータを取得する【Windows10、RaspberryPi、DragonBoard】

Node.jsでRSSのデータを取得する【Windows10、RaspberryPi、DragonBoard】

以前からちょっと欲しいなと思っていたのですが、現在のテレビ番組を一覧的に表示できなかなと。テレビをつけてEPGを見ればいいじゃないとというのはもちろんわかっているんですが、もう自分はAmazon Primeなしには生きられない特撮バカですので入力切り替えとかそんなことはもうやりたくありません。(きっぱり)

どうせ、PCつけてコードとか書いているんだしPC上で見れればそれでいいかなと思っていたんです。

テレビを見なければいいという話もあるのかもしれませんが…そういうわけにもいかないので…。

テレビの放送状況を確認するにはテレビ王国というサイトがあります。

f:id:ueponx:20170903163256p:plain

SONYさんが運営しているサービスでHDDレコーダやiEPGなんかでも使われているので比較的確度の高い情報でしょう。

tv.so-net.ne.jp

このサイトは全国のエリアをカバーしているので、自分のような地方の人間にも優しいです。また、現在の放送番組のRSSも公開されているので最高です!

RSSはこんな感じ。

Gガイド.テレビ王国 - 放送中のRSS配信 - 地上波(東京)

あとはこのRSSを読み込んでしまえば…ということになります。

今回は他のシステムとの連携もしたかったのNode.jsコーディングしました。

Node.jsでRSSを読み込む

ネットで検索したところWebのスクレイピングではcheerio-httpcliを使用すると便利そうでした。

qiita.com

cheerio-httpcli

特徴としては以下の様です。

  1. 取得先WEBページの文字コードを自動で判定してHTMLをUTF-8に変換
  2. UTF-8に変換したHTMLをjQueryのように操作可能
  3. フォームの送信やリンクのクリックをエミュレート
  4. Node.jsお馴染みのコールバック形式と最近の流行であるプロミス形式どちらにも対応
  5. 同期リクエスト対応
  6. $(‘img’)要素画像のダウンロード(LazyLoad対応)
  7. $(‘a,img,script,link’)要素のURLを絶対パスで取得可能
  8. ブラウザ指定による簡単User-Agent切り替え機能
  9. 現在のクッキーの内容を簡単に取得(読み取り専用)
  10. XMLドキュメントを自動判別してパース処理を切り替え

半分ぐらいは今回とはあまり関係はないのですが、今後使えそうな機能が多いのでこちらを採用しました。

cheerio-httpcliのインストール

今回の実行環境(Windows10)は以下の通りです。

PS C:\Users\xxx\Documents\node> node -v
v6.11.2
PS C:\Users\xxx\Documents\node> npm -v
3.10.10

インストール作業はnpmを使えば簡単です。(LinuxでもWindowsでも違いはありません。プロンプトが違うぐらいです。)

PS C:\Users\xxx\Documents\node> npm install cheerio-httpcli

問題なくインストールできました。

コーディング

先程のRSSのURLを.fetch()の引数に与えてあとは、コールバック形式かプロミス形式で処理を行えば問題ありません。プロミスってなんだろうと思ったんですが、「非同期の動作を扱う際にコールバックからメソッドチェーンにすることができコールバック地獄を回避することができる」ってことのようです。非同期処理では結構苦労するので、こういう改良が必要なんですね。

今回は規模的にはどちらを選択しても良かったのですが、せっかくなので

【sample.js】

var client = require('cheerio-httpcli');
// かんとーちほーの現在の放送番組
var RSS = "https://tv.so-net.ne.jp/rss/schedulesByCurrentTime.action?group=10&stationAreaId=23";

client.fetch(RSS, {})
.then(function (result){
    if (result.error) { console.log("error"); return; }
    result.$("item").each(function (idx) {
        programName = result.$(this).find("title").text();
        programFrame = result.$(this).find("description").text();
        console.log(programName);        
        console.log(programFrame);
        console.log("---");
    });
    console.log("\n" + "放送中番組のタイトルを取得しました。");
});

これを実行してみます。

PS C:\Users\xxx\Documents\node> node .\sample.js
Hulu傑作シアター[]
9/3 1:302:30 [日テレ(Ch.4)]
---
名棋士が読み解く 藤井聡太 “強さ”の秘密[][]
9/3 1:452:30 [NHK総合・東京(Ch.1)]
---
ワールドプロレスリング
9/3 2:002:30 [テレビ朝日(Ch.5)]
---
お買い物情報
9/3 2:002:30 [TOKYO MX1(Ch.9)]
---
HERO'S[デ]
9/3 2:05~2:45 [フジテレビ(Ch.8)]
---
ランク王国 秋のサキドリSP!
9/3 2:08~3:08 [TBS(Ch.6)]
---
深夜に発見!新shock感~一度おためしください~
9/3 2:10~2:35 [テレビ東京(Ch.7)]
---
放送休止
9/3 2:12~5:00 [NHKEテレ1・東京(Ch.2)]
---

放送中番組のタイトルを取得しました。

うまく行ったようです。これで取得できるのはタイトル、放送枠時間、放送局だけなので内容がほしい場合には RSS上のlinkタグにあるURLを更にスクレイピングする必要があるので少し面倒ですね。

終わりに

あとはうまい感じで表示できればOKですね。

少し欲を出して、番組情報も出せるようにしました。1回目のRSSスクレイピングで詳細情報のリンク先を取得し、 2回目のスクレイピングで取得するという感じなのですが、JavaScriptは非同期実行なので、データにタイミングがコードの想定とはズレてしまうようでした。 Objectに格納しようとしたら格納時にはデータがなく、どこでデータ来るのかを判別するのがちょっと難しかったでの悩んでいました。

最初に書いた

  1. 同期リクエスト対応

こちらのことを思い出して、ググってみました。 以下のリンクに同期的実行に関して情報が乗っていたのでそれを試して見ました。

【参考】 qiita.com

【sample2.js】

var client = require('cheerio-httpcli');
var RSS = "https://tv.so-net.ne.jp/rss/schedulesByCurrentTime.action?group=10&stationAreaId=23";
var programsList = [];

var result1 = client.fetchSync(RSS);
result1.$("item").each(function (idx) {
    var program = new Object();
    var programName = result1.$(this).find("title").text();
    var programFrame = result1.$(this).find("description").text();
    var programLink = result1.$(this).find("link").text();
    var result2 = client.fetchSync(programLink);
    programInfo = result2.$(".subUtileSetting").eq(0).find("p").text();

    program["Name"] = programName;
    program["Frame"] = programFrame;
    program["Link"] = programLink;
    program["Info"] = programInfo; 
    programsList.push(program);
});

programsList.forEach(function(element) {
    console.log("\n--->\n");
    console.log("番組名  :" + element["Name"]);        
    console.log("番組時間 :" + element["Frame"]);        
    console.log("番組リンク:" + element["Link"]);            
    console.log("番組詳細 :" + element["Info"]);
}); 

これを実行させると…

PS C:\Users\xxx\Documents\> node .\sample2.js

--->

番組名  :サンバリュ 「外国人観光客に思い切って注意してみました ニッポンのマナー」[]
番組時間 :9/3 13:1514:15 [日テレ(Ch.4)]
番組リンク:http://tv.so-net.ne.jp/schedule/101040201709031315.action?from=rss
番組詳細 :満開の桜の枝をポッキリ折る!市場で生魚を手でベタベタ触る!世界遺産で環境破壊!目に余るマナー違反の外国人観光客を、勇気を出して注意!すると逆ギレ&驚きの言い訳が

--->

番組名  :45th フジサンケイクラシック 最終日[][]
番組時間 :9/3 13:3014:55 [フジテレビ(Ch.8)]
番組リンク:http://tv.so-net.ne.jp/schedule/101056201709031330.action?from=rss
番組詳細 :世界基準コース富士桜に挑む!
初優勝思い出の舞台で復活V目指す岩田寛!
22歳の若武者が初の頂点へ稲森佑貴!

--->

番組名  :舞台芸術の魅力 第8回「世界の現代演劇-演劇における「20世紀」の意味-」
番組時間 :9/3 13:4514:30 [放送大学1(Ch.12)]
番組リンク:http://tv.so-net.ne.jp/schedule/101088201709031345.action?from=rss
番組詳細 :京都造形芸術大学教授 森山 直人

--->

番組名  :海外出張オトモシマス!「フランス 激レア&絶品!チョコ・ハンター」[][][]
番組時間 :9/3 13:5014:20 [NHK総合・東京(Ch.1)]
番組リンク:http://tv.so-net.ne.jp/schedule/101024201709031350.action?from=rss
番組詳細 :海外出張のプロにオトモして、世界の流行の最前線に潜入する番組。今回の出張は、フランス!激レア絶品チョコの大捜索!パリからブルターニュ地方へ。日本初上陸のチョコ!

--->

番組名  :科捜研の女16 #11[][][]
番組時間 :9/3 13:5514:50 [テレビ朝日(Ch.5)]
番組リンク:http://tv.so-net.ne.jp/schedule/101064201709031355.action?from=rss
番組詳細 :「グルメ格付け殺人!死を呼ぶ裏メニューで人間発火!?」沢口靖子()▽身元不明の外国人男性が殺害された。マリコは 被害者が事件の夜に食事したフレンチ店に鍵があると考え…

--->

番組名  :日本の話芸 林家正雀 落語「怪談牡丹灯籠から お札はがし」[][]
番組時間 :9/3 14:0014:30 [NHKEテレ1・東京(Ch.2)]
番組リンク:http://tv.so-net.ne.jp/schedule/101032201709031400.action?from=rss
番組詳細 :第698回東京落語会から林家正雀さんの「怪談牡丹灯籠から お札はがし」をお送りします(平成29818日(金) 東京・虎ノ門 ニッショーホールで収録)

--->

番組名  :今夜!最大の悲劇がー日曜劇場「ごめん、愛してる」スペシャルダイジェスト[]
番組時間 :9/3 14:0014:50 [TBS(Ch.6)]
番組リンク:http://tv.so-net.ne.jp/schedule/101048201709031400.action?from=rss
番組詳細 :クライマックスに向け大きく動き出す長瀬智也主演の胸に迫る切ない物語「ごめん、愛してる」。そこで後編のストーリー&今夜の見所をご紹介!

--->

番組名  :日曜ミステリー「嫌われ監察官 音無一六3」[] 小日向文世主演[][]
番組時間 :9/3 14:0016:00 [テレビ東京(Ch.7)]
番組リンク:http://tv.so-net.ne.jp/schedule/101072201709031400.action?from=rss
番組詳細 :連続殺人事件の現場に残されたのは、恋愛を詠った百人一首の札。怨恨か?それとも…?監察官・音無一六が“深読み力”で真相を暴く! ≪解説放送あり≫

--->

番組名  :MXショッピング
番組時間 :9/3 14:0014:30 [TOKYO MX1(Ch.9)]
番組リンク:http://tv.so-net.ne.jp/schedule/123608201709031400.action?from=rss
番組詳細 :H2OスチームFX 【スチームクリーナー】

個人的には同期的にやったほうがスッキリしますねw。コードも短いし…。

同じソースコードでRaspberryPiとDragonBoard410Cでも実行してみます。

$ node sample2.js

--->

番組名  :決定!こども囲碁名人~第38回少年少女囲碁大会~
番組時間 :9/3 14:3016:30 [NHKEテレ1・東京(Ch.2)]
番組リンク:http://tv.so-net.ne.jp/schedule/101032201709031430.action?from=rss
番組詳細 :囲碁を志す全国の小・中学生にとって日本一の栄冠をかけたあこがれの舞台「少年少女囲碁大会・全国大会」今年も、未来の井山七冠を夢見るこどもたちが熱い戦いを繰り広げた

--->

番組名  :路線バスで寄り道の旅[]
番組時間 :9/3 15:4016:30 [テレビ朝日(Ch.5)]
番組リンク:http://tv.so-net.ne.jp/schedule/101064201709031540.action?from=rss
番組詳細 :日頃秒刻みスケジュールに疲れ気味の徳さん御一行。のんび~り旅を味わうために選んだのは“路線バス"。今回、目指すのは桜木町~馬車道~山下公園で横浜の裏 通りを散策旅

--->

番組名  :大捜索ドキュメント! 屋久島“伝説の超巨大杉”[字][再]
番組時間 :9/3 16:00~16:50 [NHK総合・東京(Ch.1)]
番組リンク:http://tv.so-net.ne.jp/schedule/101024201709031600.action?from=rss
番組詳細 :世界遺産・屋久島で語られる『超巨大杉伝説』。縄文杉を超える杉の大捜索に挑んだ。最新航空調査で森をスキャンし、秘境を大冒険。ついに捜索隊は驚きの巨大杉と遭遇する!

--->

番組名  :グラチャンバレー1番は誰?開幕直前SP[字]
番組時間 :9/3 16:00~16:55 [日テレ(Ch.4)]
番組リンク:http://tv.so-net.ne.jp/schedule/101040201709031600.action?from=rss
番組詳細 :9月5日(火)開幕、グラチャンバレー!徳井義実&佐藤栞里がバレー全日本女子を直撃!気になる噂の真相を選手が激白!

--->

番組名  :なるほど!今うなぎが食べたくなるテレビ【旬は秋!画面から香ばしい香りが?!】[解][字]
番組時間 :9/3 16:00~17:00 [TBS(Ch.6)]
番組リンク:http://tv.so-net.ne.jp/schedule/101048201709031600.action?from=rss
番組詳細 :芸能界のグルメ王・渡部建が名店の秘密に迫る!★芸能界屈指の料理人・梅沢富美男が安くて美味しいうなぎレシピに挑戦!★幻の「青うなぎ」を求めて漁に出るのはみやぞん!

--->

番組名  :YOUは何しに日本へ?予習復習▽日本茶&歌声に熱狂YOUマジ惚れ来日大騒ぎ[字]
番組時間 :9/3 16:00~17:05 [テレビ東京(Ch.7)]
番組リンク:http://tv.so-net.ne.jp/schedule/101072201709031600.action?from=rss
番組詳細 :本気で日本茶学びたい!…20歳青年YOUが本場静岡でガチ住み込み修行…超高級茶葉に昇天!?■遠い異国で人生変えた…坂本九匹敵神歌にYOUが全力マジ惚れ旅■ベビ ーメタル

--->

番組名  :いただきハイジャンプ 土曜お昼にお引っ越しSP[字]
番組時間 :9/3 16:00~17:25 [フジテレビ(Ch.8)]
番組リンク:http://tv.so-net.ne.jp/schedule/101056201709031600.action?from=rss
番組詳細 :(予定変更の場合あり)
様々な一大事にJUMPが立ち向かう▽番組引っ越し記念で人気企画を厳選!6歳少年が苦手克服に挑戦…涙のワケとは?

--->

番組名  :お買い物情報
番組時間 :9/3 16:00~16:30 [TOKYO MX1(Ch.9)]
番組リンク:http://tv.so-net.ne.jp/schedule/123608201709031600.action?from=rss
番組詳細 :トゥルースリーパープレミアケア 【低反発マットレス】

--->

番組名  :障害を知り共生社会を生きる 第8回「難病を知る」
番組時間 :9/3 16:00~16:45 [放送大学1(Ch.12)]
番組リンク:http://tv.so-net.ne.jp/schedule/101088201709031600.action?from=rss
番組詳細 :愛知県立大学教授 吉川 雅博 フリーアナウンサー 岡 知沙登

問題なく動作します!まあNode.jsなんで違いは無いはずですけどね。

うまくいったようです! これで快適なAmazonPrimeの特撮ライフがおくれそうです。

Amazon Rekognitionを使ってみる

Amazon Rekognitionを使ってみる

f:id:ueponx:20170903014828p:plain

Amazon Pollyに引き続いて、Amazon RekognitionCLIで使用してみようと思います。詳細は以下のリンクにあります。

製品の詳細 - Amazon Rekognition | AWS

Rekognition では、画像内の物体、シーン、および顔を検出できます。顔を検索および比較し、有名人を認識し、不適切なコンテンツを識別することもできます。

画像認識系のものですね。MicrosoftさんのComputer Vision APIGoogleさんのCloud Vision APIに該当するもののようです。(あってる?)

Computer Vision APIazure.microsoft.com

【Cloud Vision APIcloud.google.com

最近たくさんのAPIが出てきているのであっているのか不安になってきます。 ネットを見ると機能対決に関しても面白いですが、時間とともに学習されていくこともあるので現在の状況はどうなんでしょうか。

qiita.com

AWS CLIの設定に関して

AWS CLIに関しては以前のエントリでインストールしてあると思いますので説明は省略します。

uepon.hatenadiary.com

Amazon Rekognitionを使用するためのIAMの設定する

Polly使用時と同様にAWSマネージメントコンソールから認証情報を設定する必要があります。具体的にはマネージメントコンソールからIAMを設定する必要があります。

IAMの画面からユーザの追加を選択します。今回のユーザー名はRekognition_userとして【プログラムによるアクセス】にチェックを入れ、画面下の【次のステップ:アクセス権限】ボタンをクリックします。

f:id:ueponx:20170903003330j:plain

作成されたRekognition_userの権限を追加する画面です。

f:id:ueponx:20170903003657j:plain

アクセス権限に【既存のポリシーを直接アタッチ】を選択し、フィルターの検索ボックスにRekognitionと入力して検索をします。

f:id:ueponx:20170903003748j:plain

f:id:ueponx:20170903003807j:plain

すると

  • AmazonRekognitionFullAccess
  • AmazonRekognitionReadOnlyAccess

以上の2つが候補に上がります。今回使用するポリシーはAmazonRekognitionFullAccessというポリシーになりますので、にチェックをいれて、【次のステップ:確認】ボタンをクリックします。(注意)実際には、適切な権限を与えるようにしてください。

ボタンをクリックすると、作成内容の確認画面になります。問題なければ【ユーザの作成】ボタンをクリックします。

f:id:ueponx:20170903004242j:plain

成功すると以下のような画面に遷移します。

f:id:ueponx:20170903004344j:plain

ユーザ名、アクセスキーID、シークレットアクセスキーが表示されますが、画面の中ほどにある【.csvのダウンロード】ボタンをクリックすれば、表示された情報が含まれたCSVファイルがダウンロードできるのでそれをダウンロードしておきます。この情報をあとの手順で使用します。

Amazon RekognistionAWS CLIから使用する

AMIの設定が完了したのでCLIから使用してみたいと思います。初回なのでaws configureコマンドで設定を行います。

PS C:\Users\xxx> aws configure
AWS Access Key ID [None]: <ダウンロードしたCSVに記載>
AWS Secret Access Key [None]: <ダウンロードしたCSVに記載>
Default region name [None]: us-west-2
Default output format [None]: json

Pollyの設定が残っている可能性もあるので、自分は一度設定をクリアしています。書き換える場合にはNoneとなっている部分に旧設定が入力されています。

注意点としてはRekognitionが使えるリージョンは以下の通りです。これ以外のリージョンでは使えないので注意してください。ただし、CLIのオプションで設定すればDefault設定が違っていても問題はないと思います。リージョンが異なる状態で使用すると対応していませんという旨のエラーが発生します。

リージョン名 値?
US East (N. Virginia) us-east-1
US West (Oregon) us-west-2
EU (Ireland) eu-west-1

Configureの設定が終わったので早速使用してみたいと思います。

Amazon Rekognitionのドキュメントを読むと

【参照】 docs.aws.amazon.com

AWS CLI を使用して Amazon Rekognition オペレーションを呼び出す場合、呼び出しの一部として画像のバイトを渡すことはサポートされていません。最初に Amazon S3 バケットに画像をアップロードし、次にアップロードした画像を参照するオペレーションを呼び出します。

と書いてあります。CLI経由での仕様ではバイト列の直接送信はできず、S3で画像ファイルにアクセスするしかないようです。 画像はlenaさんを使用しました。

f:id:ueponx:20170903010215j:plain

S3のBucketを作成し(Bucket名:20170831-image-sample)、画像ファイル(画像ファイル名:lena.jpg)を保存しておきたいと思います。 以下のようにBucketを作成して

f:id:ueponx:20170903010912j:plain

CLI経由で画像ファイルを転送してみます。

PS C:\Users\xxx> aws s3 cp C:\Users\xxx\lena.jpg s3://20170831-image-sample/
upload failed: Desktop\lena.jpg to s3://20170831-image-sample/lena.jpg An error occurred (AccessDenied) when calling the PutObject operation: Access Denied

あれ?そうか、IAMの設定にS3の操作権限がありませんでした。

先程設定したIAMにS3FullAccessのポリシーを追加します。アクセス権限に【既存のポリシーを直接アタッチ】を選択し、S3のフィルタをかけるとAmazonS3FullAccessが表示されると思うのでチェックを入れて追加をします。

f:id:ueponx:20170903011116j:plain

【アクセス権限の追加】ボタンをクリックします。

f:id:ueponx:20170903011411j:plain

以下のように権限が追加されてば問題はありません。

f:id:ueponx:20170903011535j:plain

では改めて、コピーをします。

PS C:\Users\xxx> aws s3 cp lena.jpg s3://20170831-image-sample/
upload: Desktop\lena.jpg to s3://20170831-image-sample/lena.jpg

無事にコピーできたようです。マネージメントコンソール上からでも以下のようにアクセスできました。

f:id:ueponx:20170903011723j:plain

(※)基本的にSDK経由でアクセスする場合にはS3上にあるファイルである必要は必ずしもありません。ただし、AWS CLI経由の場合にはS3である必要があるとのことでした。そのため権限にもS3FullAccessが必要になります。

さて、S3に画像ファイルの準備ができたのでRekognitionを使用してみます。 ここで使用しているのはdetect-labelsになります。入力として渡した画像内の物体、概念、シーンを検出してテキスト情報で返します。

PS C:\Users\xxx> aws rekognition detect-labels --image "S3Object={Bucket=20170831-image-sample,Name=lena.jpg}"
{
    "Labels": [
        {
            "Confidence": 99.27481079101562,
            "Name": "Human"
        },
        {
            "Confidence": 99.27967071533203,
            "Name": "People"
        },
        {
            "Confidence": 99.2796859741211,
            "Name": "Person"
        },
        {
            "Confidence": 53.77459716796875,
            "Name": "Female"
        },
        {
            "Confidence": 53.77459716796875,
            "Name": "Girl"
        },
        {
            "Confidence": 53.77459716796875,
            "Name": "Woman"
        },
        {
            "Confidence": 52.33949279785156,
            "Name": "Hat"
        },
        {
            "Confidence": 51.73891830444336,
            "Name": "Cap"
        },
        {
            "Confidence": 51.73891830444336,
            "Name": "Sun Hat"
        },
        {
            "Confidence": 51.37664031982422,
            "Name": "Face"
        },
        {
            "Confidence": 51.37664031982422,
            "Name": "Selfie"
        }
    ],
    "OrientationCorrection": "ROTATE_0"
}

Human、Person、Girl、Woman、Hat、Face、Selfieなど、この画像にあった検出ができているようです。Json形式で返されているのであとはこれを編集するだけですね。

detect-labels以外にもdetect-moderation-labelsという機能もあります。 Moderation(画像の「節度」)を判定する機能です。 具体的には、不適切な画像(例えばヌードや、露骨ないやらしさなど)を判定することができる機能です。

lenaさんのオリジナル画像はアレな画像なので、先程の顔だけの画像(lena.jp)と全身像の画像(lena2.jpg)でdetect-moderation-labelsを判定してみます。

【全身の画像(一応モザイクはかけました。)】 f:id:ueponx:20170903013037j:plain

【顔だけの画像】

PS C:\Users\xxx> aws rekognition detect-moderation-labels --image "S3Object={Bucket=20170831-image-sample,Name=lena.jpg}"
{
    "ModerationLabels": []
}

【全身の画像】

PS C:\Users\xxx> aws rekognition detect-moderation-labels --image "S3Object={Bucket=20170831-image-sample,Name=lena2.jpg}"
{
    "ModerationLabels": [
        {
            "Confidence": 59.9111328125,
            "ParentName": "",
            "Name": "Suggestive"
        },
        {
            "Confidence": 59.9111328125,
            "ParentName": "Suggestive",
            "Name": "Revealing Clothes"
        }
    ]
}

全身の画像ではRevealing Clothesと判別されています。正解です。

おわりに

Amazon RekognitionをAWS CLIから操作してみました。CLIではS3に画像データを置く必要があるので今ひとつですが、SDK経由であればそのようなことはないようです。画像の送信にBASE64エンコードに対応した言語であればすんなり行けるそうです。(ほとんどがOK)

個人的にはその他のサービスに比べてちょっと物足りないかな…こういうものなんでしょうか。

Amazon PollyをPythonから使ってみる

Amazon PollyをPythonから使ってみる

f:id:ueponx:20170831234755p:plain

前回のエントリーではAWS CLIからAmazon Pollyをコールしてみましたが、今度はpythonから呼び出してみたいと思います。

uepon.hatenadiary.com

Pollyに関しては各言語のドキュメントもサンプルもそろっているので行けると思います。.netからも触れるので自分の場合にはそっちからやればよかったなとは少し思いました。

【PollyのSDKのページ】

開発者用リソース - Amazon Polly | AWS

Amazon Polly(Python編)

こう書くとこのエントリー中にほかの言語も入りそうですが、Pythonのみですw。

インストール

github.com

Boto is the Amazon Web Services (AWS) SDK for Python, which allows Python developers to write software that makes use of Amazon services like S3 and EC2. Boto provides an easy to use, object-oriented API as well as low-level direct service access.

BotoAWSのPythonSDKで、Lowレベルと同等のアクセスができるようになってるってことのようです。

一応、インストールの項目通りにやってみると…

PS C:\> python --version
Python 3.6.1 :: Anaconda 4.4.0 (64-bit)
PS C:\> pip -V
pip 9.0.1 from C:\Users\xxx\Anaconda3\lib\site-packages (python 3.6)
PS C:\> pip install boto
Requirement already satisfied: boto in c:\users\xxx\anaconda3\lib\site-packages

メッセージをみると既にAnaconda環境には入っているようなのですが、サンプルソース上でimportされているのってboto3じゃなかったっけ?と思い、 スタートメニューから【Anaconda Prompt】を起動して、以下のようにインストールしてみました。

(C:\Users\xxx\Anaconda3) C:\Users\xxx>pip install boto3
Collecting boto3
  Downloading boto3-1.4.7-py2.py3-none-any.whl (128kB)
    100% |████████████████████████████████| 133kB 2.2MB/s
Collecting s3transfer<0.2.0,>=0.1.10 (from boto3)
  Downloading s3transfer-0.1.10-py2.py3-none-any.whl (54kB)
    100% |████████████████████████████████| 61kB ...
Collecting jmespath<1.0.0,>=0.7.1 (from boto3)
  Downloading jmespath-0.9.3-py2.py3-none-any.whl
Collecting botocore<1.8.0,>=1.7.0 (from boto3)
  Downloading botocore-1.7.0-py2.py3-none-any.whl (3.6MB)
    100% |████████████████████████████████| 3.6MB 225kB/s
Requirement already satisfied: docutils>=0.10 in c:\users\xxx\anaconda3\lib\site-packages (from botocore<1.8.0,>=1.7.0->boto3)
Requirement already satisfied: python-dateutil<3.0.0,>=2.1 in c:\users\xxx\anaconda3\lib\site-packages (from botocore<1.8.0,>=1.7.0->boto3)
Requirement already satisfied: six>=1.5 in c:\users\xxx\anaconda3\lib\site-packages (from python-dateutil<3.0.0,>=2.1->botocore<1.8.0,>=1.7.0->boto3)
Installing collected packages: jmespath, botocore, s3transfer, boto3
Successfully installed boto3-1.4.7 botocore-1.7.0 jmespath-0.9.3 s3transfer-0.1.10

予想通りboto3はインストールされてなかった…サンプルソースでは普通に使用しているのに。

先程のページにはこんな記述が、今後はこっちをみてねってことっぽい。

Boto3, the next version of Boto, is now stable and recommended for general use. It can be used side-by-side with Boto in the same project, so it is easy to start using Boto3 in your existing projects as well as new projects. Going forward, API updates and all new feature work will be focused on Boto3.

github.com

C:\Users\xxx> python
Python 3.6.1 |Anaconda 4.4.0 (64-bit)| (default, May 11 2017, 13:25:24) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> from boto3 import Session
>>>

一応、Anaconda環境でないPowerShellのREPLでも動作したので大丈夫です。

使ってみる

ドキュメントはこちら↓

Boto 3 Documentation — Boto 3 Docs 1.4.7 documentation Amazon Polly のドキュメント

BotoAWSサービス制御用のSDKなのでドキュメントもS3EC2などの項目も入っています(というかそっちがメイン)。

上記のリンクからPollyの項目をみつけます。

Polly — Boto 3 Docs 1.4.7 documentation

公式ドキュメントをみると以下のような記載する旨が書かれています。

# Create a client using the credentials and region defined in the [adminuser]
# section of the AWS credentials file (~/.aws/credentials).
session = Session(profile_name="adminuser")
polly = session.client("polly")

ここでいう~/.aws/credentialsaws configure実行時にいれた情報が入ります。credentialsは認証情報、同じディレクトリにある~/.aws/configはregion情報が含まれています。 初期値はdefaultユーザになっているのでドキュメントに従うのであれば

【変更前】

session = Session(profile_name="adminuser")

【変更後】

session = Session(profile_name="default")

になるのですが、defalutの場合には省略できるようで、

polly = boto3.client("polly")

これでもいいのかなと思います。 【参考】 Session — Boto 3 Docs 1.4.7 documentation

もし、リージョン設定が複数跨る場合には(例えば、同時使用するS3とリージョンが異なる場合など)

from boto3 import Session
...
session = Session(region_name="us-west-2")
polly = session.client("polly")

となります。引数で渡しても問題ないようです。大体の基本形はこんな感じになると思います。

from boto3 import Session
...
# 個人的にはリージョンは指定する方が無難かなと思います。
session = Session(region_name="us-west-2")
polly = session.client("polly")
try:
  # TTSの機能をここで呼び出す。CLIの引数はここで指定するイメージ
  response = polly.synthesize_speech(Text="Hello world!", OutputFormat="mp3", VoiceId="Joanna")
except (BotoCoreError, ClientError) as error:
 ...

サンプルコードを眺めながら触ってこんな感じに編集しました。 mainの部分はなくてもいいかなと思います。

【ドキュメントサンプル写経版・改】

"""Getting Started Example for Python 2.7+/3.3+"""
from boto3 import Session
from botocore.exceptions import BotoCoreError, ClientError
from contextlib import closing
import os
import sys
import subprocess
from tempfile import gettempdir
# Create a client using the credentials and region defined in the [adminuser]
# section of the AWS credentials file (~/.aws/credentials).
session = Session(region_name="us-west-2")
polly = session.client("polly")
try:
    # Request speech synthesis
    response = polly.synthesize_speech(Text="Hello world!", OutputFormat="mp3", VoiceId="Joanna")
except (BotoCoreError, ClientError) as error:
    # The service returned an error, exit gracefully
    print(error)
    sys.exit(-1)
# Access the audio stream from the response
if "AudioStream" in response:
    # Note: Closing the stream is important as the service throttles on the
    # number of parallel connections. Here we are using contextlib.closing to
    # ensure the close method of the stream object will be called automatically
    # at the end of the with statement's scope.
    with closing(response["AudioStream"]) as stream:
        # output = os.path.join(gettempdir(), "speech.mp3") # サンプルではtmpフォルダになるけど、わかりにくい場所になるので下記に変更
        output = "speech.mp3"
        try:
            # Open a file for writing the output as a binary stream
            with open(output, "wb") as file:
                file.write(stream.read())
        except IOError as error:
            # Could not write to file, exit gracefully
            print(error)
            sys.exit(-1)
        print("create OK>>" + output)
else:
    # The response didn't contain audio data, exit gracefully
    print("Could not stream audio")
    sys.exit(-1)

ちょっと戸惑ったのはpsynthesize_speech()の戻り値がストリーム(AudioStream)になっているので、それをファイルに書き込む必要があるという点かなと思います。with closing()...の下りはC#とかでいうところのIDisposableインターフェイスを持ったオブジェクトのusing (FileStream fs = new FileStream(…)と同じような表現のようです。

あとサンプルではoutput = os.path.join(gettempdir(), "speech.mp3")のようにテンポラリ領域にファイルを入れるようにしているのですが。Windows10の場合にはかなりわかりにくいところに保存されます。C:\Users\【ユーザ名】\AppData\Local\Tempに格納されます。さすがにわかりにくいので今回はテンポラリは使用せずにカレントに保存するように変えています。

コメントがあるので冗長に感じますが、コメントを除いて簡略化するとこんな感じになります。

【シンプル版サンプル・日本語版】

from boto3 import Session
from botocore.exceptions import BotoCoreError, ClientError
from contextlib import closing
import os
import sys
import subprocess

session = Session(region_name="us-west-2")
polly = session.client("polly")
try:
    response = polly.synthesize_speech(Text="ひとっ走り付き合えよ", OutputFormat="mp3", VoiceId="Mizuki")
except (BotoCoreError, ClientError) as error:
    print(error)
    sys.exit(-1)
if "AudioStream" in response:
    with closing(response["AudioStream"]) as stream:
        output = "speech.mp3"
        try:
            with open(output, "wb") as file:
                file.write(stream.read())
        except IOError as error:
            print(error)
            sys.exit(-1)
        print("synthesize_speech OK ->>" + output)
else:
    print("Could not stream audio")
    sys.exit(-1)

そこそこわかりやすくなったような気がします。あとはmpg321などを外部コマンドで呼び出すか、pygameにmp3を渡せばそのまま音声出力ができるかなと思います。(後述)

【参考】 uepon.hatenadiary.com

おまけ【RaspberryPiでもPython経由でAmazon Polly】

RaspberryPiからも使ってみます。

インストール

$ pip install boto3
Collecting boto3
  Downloading boto3-1.4.7-py2.py3-none-any.whl (128kB)
    100% |????????????????????????????????| 133kB 1.0MB/s
Collecting botocore<1.8.0,>=1.7.0 (from boto3)
  Downloading botocore-1.7.1-py2.py3-none-any.whl (3.6MB)
    100% |????????????????????????????????| 3.6MB 40kB/s
Collecting jmespath<1.0.0,>=0.7.1 (from boto3)
  Using cached jmespath-0.9.3-py2.py3-none-any.whl
Collecting s3transfer<0.2.0,>=0.1.10 (from boto3)
  Using cached s3transfer-0.1.10-py2.py3-none-any.whl
Collecting python-dateutil<3.0.0,>=2.1 (from botocore<1.8.0,>=1.7.0->boto3)
  Using cached python_dateutil-2.6.1-py2.py3-none-any.whl
Collecting docutils>=0.10 (from botocore<1.8.0,>=1.7.0->boto3)
  Using cached docutils-0.14-py2-none-any.whl
Collecting futures<4.0.0,>=2.2.0; python_version == "2.6" or python_version == "2.7" (from s3transfer<0.2.0,>=0.1.10->boto3)
  Using cached futures-3.1.1-py2-none-any.whl
Collecting six>=1.5 (from python-dateutil<3.0.0,>=2.1->botocore<1.8.0,>=1.7.0->boto3)
  Using cached six-1.10.0-py2.py3-none-any.whl
Installing collected packages: six, python-dateutil, docutils, jmespath, botocore, futures, s3transfer, boto3
Successfully installed boto3-1.4.7 botocore-1.7.1 docutils-0.14 futures-3.1.1 jmespath-0.9.3 python-dateutil-2.6.1 s3transfer-0.1.10 six-1.10.0

実行

$ python polly_simple.py
synthesize_speech OK ->>speech.mp3
$ ls speech.mp3
speech.mp3

ただし、このやり方はpython2.7で動作させているのでShebangとマジックコメントをつけないと日本語で死ぬとエラーがでると思います。下記のようなエラーが出た場合対応する必要があります。

$ python polly_simple.py
  File "polly_simple.py", line 11
SyntaxError: Non-ASCII character '\xe3' in file polly_simple.py on line 11, but no encoding declared; see http://python.org/dev/peps/pep-0263/ for details

【python2なコード】

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from boto3 import Session
from botocore.exceptions import BotoCoreError, ClientError
from contextlib import closing
import os
import sys

session = Session(region_name="us-west-2")
polly = session.client("polly")
try:
    response = polly.synthesize_speech(Text="ひとっ走り付き合えよ", OutputFormat="mp3", VoiceId="Mizuki")
except (BotoCoreError, ClientError) as error:
    print(error)
    sys.exit(-1)
if "AudioStream" in response:
    with closing(response["AudioStream"]) as stream:
        output = "speech.mp3"
        try:
            with open(output, "wb") as file:
                file.write(stream.read())
        except IOError as error:
            print(error)
            sys.exit(-1)
        print("synthesize_speech OK ->>" + output)
else:
    print("Could not stream audio")
    sys.exit(-1)

python3系での実行

もしPython3系で動作させるならインストールはpipではなくpip3で行います。実行もpythonではなくpython3で実行します。

【インストール】

$ pip3 install boto3
Collecting boto3
  Using cached boto3-1.4.7-py2.py3-none-any.whl
Collecting s3transfer<0.2.0,>=0.1.10 (from boto3)
  Using cached s3transfer-0.1.10-py2.py3-none-any.whl
Collecting jmespath<1.0.0,>=0.7.1 (from boto3)
  Using cached jmespath-0.9.3-py2.py3-none-any.whl
Collecting botocore<1.8.0,>=1.7.0 (from boto3)
  Using cached botocore-1.7.1-py2.py3-none-any.whl
Collecting docutils>=0.10 (from botocore<1.8.0,>=1.7.0->boto3)
  Downloading docutils-0.14-py3-none-any.whl (543kB)
    100% |????????????????????????????????| 552kB 489kB/s
Collecting python-dateutil<3.0.0,>=2.1 (from botocore<1.8.0,>=1.7.0->boto3)
  Using cached python_dateutil-2.6.1-py2.py3-none-any.whl
Collecting six>=1.5 (from python-dateutil<3.0.0,>=2.1->botocore<1.8.0,>=1.7.0->boto3)
  Using cached six-1.10.0-py2.py3-none-any.whl
Installing collected packages: docutils, jmespath, six, python-dateutil, botocore, s3transfer, boto3
Successfully installed boto3-1.4.7 botocore-1.7.1 docutils-0.14 jmespath-0.9.3 python-dateutil-2.6.1 s3transfer-0.1.10 six-1.10.0

$ python3 polly_simple3.py
synthesize_speech OK ->>speech.mp3

【Python3用のソース】…このソースではpygameを使って再生まで行っています。pygameではイベントハンドラpygame.event.get():)を使って再生中の状態をイベントで取得できますが、画面のない場合にはエラーとなってしまします(コンソールでは実行できない)。そのため、pygame.mixer.music.get_busy()を使って再生中であるか否かを判別しています。 イベントが使用できない点は以下に記載があります。

Pygame handles all it’s event messaging through an event queue. The routines in this module help you manage that event queue. The input queue is heavily dependent on the pygame display module. If the display has not been initialized and a video mode not set, the event queue will not really work. pygame.event — Pygame v1.9.2 documentation

【Python3用のソース】

from boto3 import Session
from botocore.exceptions import BotoCoreError, ClientError
from contextlib import closing
import os
import sys
import pygame.mixer

session = Session(region_name="us-west-2")
polly = session.client("polly")
try:
    response = polly.synthesize_speech(Text="ひとっ走り付き合えよ", OutputFormat="mp3", VoiceId="Mizuki")
except (BotoCoreError, ClientError) as error:
    print(error)
    sys.exit(-1)
if "AudioStream" in response:
    with closing(response["AudioStream"]) as stream:
        output = "speech.mp3"
        try:
            with open(output, "wb") as file:
                file.write(stream.read())
        except IOError as error:
            print(error)
            sys.exit(-1)
        print("synthesize_speech OK ->>" + output)
else:
    print("Could not stream audio")
    sys.exit(-1)
pygame.init()
pygame.mixer.init()
pygame.mixer.music.load("speech.mp3")
pygame.mixer.music.play()
while pygame.mixer.music.get_busy() == True:
    continue
pygame.mixer.music.stop()
pygame.mixer.quit()
pygame.quit()

【実行】

from boto3 import Session
from botocore.exceptions import BotoCoreError, ClientError
from contextlib import closing
import os
import sys
import pygame.mixer

session = Session(region_name="us-west-2")
polly = session.client("polly")
try:
    response = polly.synthesize_speech(Text="ひとっ走り付き合えよ", OutputFormat="mp3", VoiceId="Mizuki")
except (BotoCoreError, ClientError) as error:
    print(error)
    sys.exit(-1)
if "AudioStream" in response:
    with closing(response["AudioStream"]) as stream:
        output = "speech.mp3"
        try:
            with open(output, "wb") as file:
                file.write(stream.read())
        except IOError as error:
            print(error)
            sys.exit(-1)
        print("synthesize_speech OK ->>" + output)
else:
    print("Could not stream audio")
    sys.exit(-1)
pygame.init()
pygame.mixer.init()
pygame.mixer.music.load("speech.mp3")
pygame.mixer.music.play()
while pygame.mixer.music.get_busy() == True:
    continue
pygame.mixer.music.stop()
pygame.mixer.quit()
pygame.quit()

うまく音声ファイルの再生までできました。

終わりに

今回はAmazon PollyをPythonから触るPython編というエントリーとしていますが、その多言語からでもドキュメントやサンプルがしっかりしているので問題なく使えると思います。CLIだけでなくいろいろな言語から呼び出せることで、ツイッターからの読み上げなんていうのも簡単にできそうですね。

Windows10にPyCharmをインストールしてみる

Windows10にPyCharmをインストールしてみる

前から興味はあったのですが、なかなかインストールできなかったpythonIDE環境PyCharmをインストールしてみました。PyCharmはあのIntelliJ IDEAやReSharperで有名なJetBrainsさんのIDEですので、かなり期待期待しています。いまのところVScodeVim(ほとんど設定のされていない)でpythonのコードを書いていますが、pythonシンタックスにそんなに詳しいわけでもないので(というかかなり間違える)のでやっぱIDE入れるしかねえと思ってます。

インストール作業

下記のサイトにいってまずはダウンロードになります。

www.jetbrains.com

画面中の【Download Now】のボタンをクリックすると

f:id:ueponx:20170830181746p:plain

【Professional】か【Community】のエディション選択になります。自分はFreeでも十分かなと思っているので【Community】エディションを選びました。Communityエディションの【Download】ボタンをクリックします。

f:id:ueponx:20170827135449j:plain

ダウンロードすると以下のファイルが保存されます。(2017/08/27現在)

f:id:ueponx:20170827135500j:plain

ダウンロード後はWeb画面は以下のようになりますが、ほおっておいても問題ないでしょう。 内容は手順の説明などになっています。

f:id:ueponx:20170827135508j:plain

インストーラを起動します。ここは【Next】ボタンをクリックします。 (ほかのアプリは落としたほうがいいよって内容です)

f:id:ueponx:20170827135517j:plain

次はインストールパスの設定です。基本デフォルトでいいと思います。変更しないなら【Next】ボタンをクリックします。

f:id:ueponx:20170827135532j:plain

続いてインストールオプションの設定になります。デスクトップのランチャー(ショートカットの作成)や拡張子の関連付けの設定になります。

f:id:ueponx:20170827135538j:plain

自分は以下のように設定しましたが、正直、拡張子の関連付けはいらないかもなあ…とは思います。設定が終わったら【Next】ボタンをクリックします。

f:id:ueponx:20170827135542j:plain

続いてスタートメニューの設定になりますが、変更しないなら【Install】ボタンをクリックします。

f:id:ueponx:20170827135551j:plain

あとはプログレスバーが100%になるのを待ちます。意外と長かったなという印象でした。

f:id:ueponx:20170827135557j:plain

処理が完了するとセットアップは完了になりますので【Finish】ボタンをクリックします。Finishと同時にPyCharmを起動したい場合はチェックをしてください。

f:id:ueponx:20170827135605j:plain

先ほどインストール作業でデスクトップにショートカットの作成を行ったので、以下のようなアイコンができていれば大丈夫です。インストーラーの作業はこれで終わるのですが、JetBrainsのアプリケーションでは初回の起動でも設定する必要があります。

f:id:ueponx:20170827135611j:plain

デスクトップのショートカットをクリックしてPyCharmを起動すると

f:id:ueponx:20170827135620j:plain

過去バージョンの設定を引き継ぐか尋ねられます。初回なのでラジオボタンを【Do not import setting】とし、【OK】ボタンをクリックします。

続いてJetBrainsさんのプライバシーポリシーの同意を求められますので【Accept】ボタンをクリックします。

f:id:ueponx:20170827135630j:plain

これでPyCharmのスプラッシュスクリーンが表示されるのでインストール終わった!と思うのですが。

f:id:ueponx:20170827135636j:plain

キーマップ、テーマ、アイコン、フォントの設定を行うダイアログが表示されます。あとからでも変えられるのでここでは【OK】ボタンをクリックします。

f:id:ueponx:20170827135643j:plain

やっと起動できました!万歳!見た目もなんとなくIntelliJ IDEAに似ていますっていうかそのものに近い。

f:id:ueponx:20170827135650j:plain

あとはプロジェクトを作成(【Create New Project】)を選択して、開発を始めることになります。

f:id:ueponx:20170831001408j:plain

【Create New Project】をクリックするとプロジェクトの場所【Location】と【Interpreter】(実行するPythonの場所)の選択のダイアログが表示されます。【Interpreter】の欄の右にある歯車をボタンクリックするとVirtualENVなども設定できるようです。

f:id:ueponx:20170827135657j:plain

これで終わったと思うのですが、実は起動後もファイルの設定などを行っているので即テストコードをつくって実行しようとするとRunできないという罠があります(メニューがそもそもアクティブにならない。)。少し待つとGUIのボタンなどもアクティブになるので心配はありません。

Tipsのダイアログは消して作業を進めます。

プロジェクトペイン上で作成したプロジェクトで上で右クリックし【NEW】→【Python File】を選択します。

f:id:ueponx:20170831002150j:plain

ファイル名入力のダイアログが表示されるので入力します。

f:id:ueponx:20170831003140p:plain

ファイルの編集を行ったら

f:id:ueponx:20170831010811j:plain

メニューバー上の【RUN】→【RUN】を選択します。

f:id:ueponx:20170831010830j:plain

実行ファイルの選択ダイアログが表示されるので、対象となるファイルを選択します。

f:id:ueponx:20170831011204j:plain

すると、ウインドウの下部に実行時のコンソールが開きます。これで実行完了です。

f:id:ueponx:20170831012415j:plain

終わりに

ブレークポイントの指定をしたデバックや変数のモニタもできます。いままでとは大違いで開発が容易になりました!スニペットも使えるし、ハイライトも、ファイルのDiffも取れるので超便利!いろいろ捗るので今後も使っていこうと思います。

/* -----codeの行番号----- */