TomoProgの技術書

底辺プログラマーが達人プログラマーになるまで

Effective Pythonを買ってみた

皆さん
こんにちは、こんばんは
TomoProgです。

今日は題名の通り、「Effective Python」というPythonプログラムを書く上でのノウハウ本が売っていたので、買ってみました。

f:id:TomoProg:20160228193308j:plain
http://www.amazon.co.jp/Effective-Python-%E2%80%95Python%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0%E3%82%92%E6%94%B9%E8%89%AF%E3%81%99%E3%82%8B59%E9%A0%85%E7%9B%AE-Brett-Slatkin/dp/4873117569

まだ、20ページほどしか読んでいないですが、ジェネレータやリスト内包表記など自分が普段使っていないテクニックの使い方や、Pythonで書くのであればこのように書いたほうが良いというプログラムの書き方など、我流でPythonを勉強した私にとっては得るものが多い書籍だなと感じています。

この本で学習したことはこのブログで掲載していけたらと思います。

それではまた。

TomoProg

GitHub
TomoProg (TomoProg) · GitHub

Twitter
TomoProg (@tomoprog_xxx) | Twitter

Vimのインデントをファイル形式ごとに設定してみた

皆さん
こんにちは、こんばんは
TomoProgです。

皆さんVim使っていますか?
あんな気違いなエディタ使わねぇよ・・・
という人も多いと思いますが、私はよくVimを使います。

何故かって?
それは、
「俺、Vim使えるよ。」
ってドヤ顔できるからです!!

という半分冗談は置いておき、
今日はVimでのプログラミングを快適にするべく、ファイル形式ごとにインデントを設定してみました。

それでは頑張っていきましょう。

Vimって何?

設定に入る前に、Vimを少し紹介しておきましょう。

Vimテキストエディタの一つです。
Windowsで言うとメモ帳と一緒の部類ですね。

ただ、メモ帳と大きく異る点があります。
それはVimCUIベースのテキストエディタだということです。

CUIベースというとあれです。
映画とかでハッカーが黒い画面にカタカタと謎のコマンドを打ち込んでいるときがあると思います。
あの黒い画面上で起動するエディタがVimです!!

基本的にマウスが使えません!!
×ボタンで閉じるとかありません!!
名前をつけて保存ボタンとかありません!!

全部コマンドで処理します。

メモ帳みたいにスタートメニューから起動するなんてそんなことしません。
ターミナルを立ち上げて、コマンドを入力します。

$ vim ファイル名

そんなエンジニア向けのエディタ
それが、Vimです。

.vimrcにてプラグイン機能をONにする

さっそくVimを設定していきます。
ホームディレクトリ配下に.vimrcファイルを作成し、以下の一文を記述します。

filetype plugin indent on

これで、ファイル形式別にインデントを設定する機能が有効になりました。

filetypeを記述する

.vimディレクトリ内にfiletype.vimというファイルを作成し、インデントを設定するファイル形式を記述します。
pythonの場合はこんな感じです。

augroup filetypedetect
    au BufRead,BufNewFile *.py setfiletype python
augroup END

filetypeに対応する設定を記述する

.vimディレクトリ内にftpluginディレクトリを作成し、filetypeで指定したsetfiletypeの名前でファイルを作成します。
今回はsetfiletypeにpythonを指定したのでpython.vimという名前でファイルを作成します。

私は以下の内容をpython.vimに設定しました。

set expandtab
set tabstop=4
set softtabstop=4
set shiftwidth=4

これで、.pyのファイルではタブが4つのスペースで入力されるようになりました!!

まとめ

  • ファイル形式ごとにVimのインデントを変更出来る!!

今日はVimのインデントをファイル形式ごとに設定してみました。
Pythonでプログラム書くときに毎回タブからスペースに変換していたので、この設定にしてからすごく快適です!!
それではまた。

TomoProg

GitHub
TomoProg (TomoProg) · GitHub

Twitter
TomoProg (@tomoprog_xxx) | Twitter

Pythonで百人一首ボットを作ってみる!! パート2

皆さん
こんにちは、こんばんは
TomoProgです。

前の投稿から少し期間が空いてしまいましたが気にせず、書いていこうと思います。
今回は百人一首ボット作りのパート2です!!

パート1を見ていない方はパート1からどうぞ!!
tomoprog.hatenablog.com

パート1では絵札をTwitterに投稿するところまで出来ました。
今回は絵札と一緒に歌も投稿してみたいと思います。

それでは頑張っていきましょう。

歌と歌人を集める

まずは歌の上の句、下の句を集めるところからスタートです。
今回は以下のサイトを利用し、集めてみます。
百人一首の一覧

集め方はこんな感じです。

  1. 上記のサイトを全コピーし、テキストエディタにペースト
  2. 空行などの不必要な行を全削除して保存
  3. 保存したテキストファイルを表計算ソフトで開く
  4. CSVファイルとして保存

プログラムは一行も書きません!!

実際にやってみると、こんな感じです。
f:id:TomoProg:20160224225421j:plain

次は歌人を集めます。
と言ってもさっきとサイトが違うだけで、やり方はほぼ一緒です。
利用したサイトは以下のサイトです。
小倉百人一首の歌人名前・読み方

これで歌と歌人は準備出来ました。

jsonフォーマットに整形してみる

先ほど作ったCSVファイルのまま使用してもいいのですが、今回は勉強も兼ねてjsonフォーマットに整形してみました。
Pythonにはjsonというjsonファイルを扱う標準モジュールがあります。
19.2. json — JSON エンコーダおよびデコーダ — Python 3.6.5 ドキュメント

jsonモジュールを使って以下のCSV形式のテキストファイルを読み込んで、jsonフォーマットに整形してみます。

CSVファイル:
天智天皇,てんじてんのう,秋の田のかりほの庵の苫をあらみ,わが衣手は露にぬれつつ
持統天皇,じとうてんのう,春過ぎて夏来にけらし白妙の,衣干すてふ天の香具山
柿本人麻呂,かきのもとのひとまろ,あしびきの山鳥の尾のしだり尾の,ながながし夜をひとりかも寝む
(以下省略・・・)
#-*- coding:utf-8 -*-

import json

json_info = []
cnt = 1

with open("karuta_info.csv") as f:
    f_str = []
    for line in f:
        f_str.append(line)

for line in f_str:
    d = {}
    line = line.rstrip("\n")
    info = line.split(",")
    info.append(str(cnt).zfill(3) + ".jpg")
    d["name"] = info[0]         # 歌人名
    d["hurigana"] = info[1]     # ふりがな
    d["first_part"] = info[2]   # 上の句
    d["last_part"] = info[3]    # 下の句
    d["img"] = info[4]          # 画像名
    json_info.append(d)
    cnt += 1

with open("karuta_info.json", "w") as f_json:
    for info in json_info:
        json.dump(info, f_json, sort_keys=True, indent=4, ensure_ascii=False)
        f_json.write("\n")
実行結果:
{
    "first_part": "秋の田のかりほの庵の苫をあらみ",
    "hurigana": "てんじてんのう",
    "img": "001.jpg",
    "last_part": "わが衣手は露にぬれつつ",
    "name": "天智天皇"
}
{
    "first_part": "春過ぎて夏来にけらし白妙の",
    "hurigana": "じとうてんのう",
    "img": "002.jpg",
    "last_part": "衣干すてふ天の香具山",
    "name": "持統天皇"
}
{
    "first_part": "あしびきの山鳥の尾のしだり尾の",
    "hurigana": "かきのもとのひとまろ",
    "img": "003.jpg",
    "last_part": "ながながし夜をひとりかも寝む",
    "name": "柿本人麻呂"
}
(以下省略・・・)

json.dumpを使えば辞書型から簡単にjsonフォーマットに変換できるので便利です!!

つぶやいてみる

百人一首の情報を一つのjsonファイルにまとめたので、あとは読み込んでTwitterに投稿するだけです!!
早速やってみましょう。

#-*- coding:utf-8 -*-

from twitter import *
import json
import datetime
import time
import random
import copy
import os

# global変数
app = None
app_up = None
app_auth = None
conf_file_name = "conf.json"
karuta_info_file_name = "karuta_info.json"

def main():
    """
        Content:
            エントリーポイント
    """

    global app
    global app_up
    global app_auth
    global conf_file_name
    global karuta_info_file_name

    # 設定ファイル読み込み
    with open(conf_file_name) as f:
        conf_data = json.loads(f.read())

    # Twitterアプリ認証
    app_auth = OAuth(conf_data["access_token"],
                conf_data["access_token_secret"],
                conf_data["consumer_key"],
                conf_data["consumer_secret"])
    app = Twitter(auth=app_auth)
    app_up = Twitter(domain="upload.twitter.com", auth=app_auth)

    # 百人一首ファイル読み込み
    karuta_info = []
    with open(karuta_info_file_name) as f:
        for line in f:
            karuta_info.append(json.loads(line))

    # 初回起動メッセージをつぶやく
    tweet_time = datetime.datetime.now()
    tweet_msg = """
                karuta_bot.pyが起動したよ!!
                これから5分毎に百人一首をつぶやくよ!!
                """
    app.statuses.update(status=tweet_msg)

    # 5分毎につぶやく
    tweet_karuta_list = copy.deepcopy(karuta_info)
    while True:
        now_time = datetime.datetime.now()
        if int((now_time - tweet_time).seconds / 300) >= 1:
            idx = random.randint(0, len(tweet_karuta_list) - 1)
            karuta_tweet(tweet_karuta_list.pop(idx))
            if not tweet_karuta_list:
                tweet_karuta_list = copy.deepcopy(karuta_info)
            tweet_time = now_time
        time.sleep(10)

def karuta_tweet(karuta_info):
    """
        Content:
            つぶやく
    """

    global app
    global app_up

    # 画像アップロード
    file_path = os.path.join("./karuta_img/", karuta_info["img"])
    with open(file_path, "rb") as image_f:
        image_data = image_f.read()
    id_img = app_up.media.upload(media=image_data)["media_id_string"]

    tweet_msg = (karuta_info["first_part"] + "\n" +
                karuta_info["last_part"] + "\n" +
                karuta_info["name"])

    # 画像とメッセージを投稿
    app.statuses.update(status=tweet_msg, media_ids=id_img)

if __name__ == "__main__":
    main()

jsonファイルから1首ランダムに選び出して、Twitterに投稿しています。

実際に起動してみた様子はこんな感じです。
毎日百人一首くん (@TomoProgBot) | Twitter
f:id:TomoProg:20160225002145j:plain

これでTwitterに自由に画像付きツイートを投稿出来そうです!!

今日の成果

  • 画像と同時に歌と歌人を投稿できた!!
  • jsonモジュールの使い方を勉強できた!!

あとは現代語訳を投稿するだけですね。
次で完成しそうです!!

それではまた。

TomoProg

GitHub
TomoProg (TomoProg) · GitHub

Twitter
TomoProg (@tomoprog_xxx) | Twitter

Pythonでは関数の引数はすべて参照渡し?

皆さん
こんにちは、こんばんは
TomoProgです。

Pythonの関数の引数がすべて参照渡しということを知っていますか?
私はPythonを趣味で使い始めてそろそろ一年ぐらいだと思いますが、知らなかったです・・・。

ということで、
今日はPythonの関数の引数について少し調べてみたことをここに書いていこうと思います。

それでは頑張っていきましょう。

ほんとに参照渡しなの!?

関数の引数がすべて参照渡しらしいので、こんなコードを書いてみました。

#-*- coding:utf-8 -*-

def calc(y):
    y += 10

def main():
    x = 10
    calc(x)
    print(x)

if __name__ == "__main__":
    main()

すべて参照渡しならば結果は20になるはずだ!!

実行結果:
10

あれ?
参照渡しなのに20になっていないんですけど、どうゆうことなんでしょう・・・。

変数の識別値を調べてみる

Pythonには組み込み関数としてid()という関数が準備されています。

id(object)
オブジェクトの “識別値” を返します。この値は整数で、このオブジェクトの有効期間中は一意かつ定数であることが保証されています。有効期間が重ならない 2 つのオブジェクトは同じ id() 値を持つかもしれません。
引用元:2. 組み込み関数 — Python 3.4.3 ドキュメント

この組み込み関数を使用して先ほどのプログラムの変数の識別値を調べてみます。

#-*- coding:utf-8 -*-

def calc(y):
    print("id(y):" + str(id(y)))
    y += 10

def main():
    x = 10
    print("id(x):" + str(id(x)))
    calc(x)
    print(x)

if __name__ == "__main__":
    main()
実行結果:
id(x):10106112
id(y):10106112
10

確かに識別値は一緒なので、参照渡しであることは間違いないみたいです。
参照渡しなのになぜ値が変わらないのかgoogle先生に聞いてみることにします。

ミュータブルとイミュータブル

先生が教えてくれたのは以下のサイトでした。
rcmdnk.github.io

なるほど。
Pythonで使用できるオブジェクトにはミュータブル(変更可能)とイミュータブル(変更不可)のオブジェクトがあるみたいです。

# ミュータブルオブジェクト
list, set, dict など

# イミュータブルオブジェクト
int, float, str, tuple など

先ほど私が作ったプログラムの引数はintでイミュータブルなので変わらなかったようです。

ミュータブルなオブジェクトを引数にしてみる

ミュータブルオブジェクトなら値が書き変わるのか見てみます。
今回はリスト型で試してみました。

#-*- coding:utf-8 -*-

def func(dist):
    dist[0] = 2
    dist[1] = "apple"
    dist[2] = False

def main():
    src = [1, "banana", True] 
    print(src)

    func(src)
    print(src)

if __name__ == "__main__":
    main()
実行結果:
[1, 'banana', True]
[2, 'apple', False]

おぉ!!
確かにミュータブルオブジェクトであれば値が書き変わりました!!

まとめ

  • Pythonでは関数の引数はすべて参照渡しである。
  • 参照渡しでも書き換え可能なオブジェクトと書き換え不可能なオブジェクトが存在する。

今日はPythonの関数の引数について調べてみました。
1年使っても知らないことは多いものです。
それではまた。

TomoProg

GitHub
TomoProg (TomoProg) · GitHub

Twitter
TomoProg (@tomoprog_xxx) | Twitter

Pythonで百人一首ボットを作ってみる!! パート1

皆さん
こんにちは、こんばんは
TomoProgです。

前々回のブログ「Python使ってつぶやいてみた」でTwitterへ投稿するやり方を学びました。
これを応用して百人一首ボットを作ってみたいと思います。

それでは頑張っていきましょう!!

百人一首ボットの仕様

まずは仕様を考えるところからスタートです。
とりあえず、考えてみた仕様はこんな感じ。

  • 何分か毎に百首の中から一首ランダムに選びTwitterに投稿する。
  • 投稿する内容はランダムに選ばれた歌の上の句、下の句、歌人名、現代語訳、絵札の画像とする。

何分毎にするかは後々決めていきます。
また、投稿する内容が多いので、投稿を分割するかもしれません。
その辺りは作りながら決めていきましょう!!

絵札の画像を集めてみる

一番時間がかかりそうな絵札画像の収集からやっていきます。
百人一首の絵札の画像は探せば沢山の種類がネット上にありますが、今回は下記のサイトの絵札画像を収集していきます。
Ogura Hyakunin Isshu - Wikimedia Commons

このサイトに表示されている画像はサムネイル用なので、前回の画像収集プログラムの時にもやったようにaタグのhref属性のURLから取得していきます。

<!-- imgタグのsrc属性はサムネイル用なので、aタグのhref属性のURLからオリジナルを取得していく -->
<a href="/wiki/File:Hyakuninisshu_003.jpg" class="image">
<img alt="" src="https://upload.wikimedia.org/wikipedia/commons/thumb/f/f6/Hyakuninisshu_003.jpg/86px-Hyakuninisshu_003.jpg" width="86" height="120" ・・・ />

そしてここで気づいたのです。
そう。このhref属性はルート記号("/")から始まってるのです。

普通にhref属性の内容でURLを開こうとすると「404 Not Found」でオリジナルの画像のURLまで辿りつけないのです・・・。

というわけで、href属性の前方にルートディレクトリのパス(https://commons.wikimedia.org/)をつけて、そのURLにアクセスし、画像を集めることにしました。

これでなんとか画像はすべて全部ゲット出来ました!!

f:id:TomoProg:20160217232156j:plain

とりあえず画像付きでつぶやいてみる

画像をTwitter上に投稿するコードを公式のサンプルプログラムを参考に書いてみることにします。
twitterモジュールのドキュメントにアップロードのやり方が書いてあったので、参考に書いてみました。
twitter · PyPI

#-*- coding:utf-8 -*-

from twitter import *
import json

# global変数
conf_file_name = "conf.json"

def main():
    """
        Content:
            エントリーポイント
    """
    # 設定ファイル読み込み
    with open(conf_file_name) as f:
        conf_data = json.loads(f.read())

    # Twitterアプリ認証
    app_auth = OAuth(conf_data["access_token"],
                conf_data["access_token_secret"],
                conf_data["consumer_key"],
                conf_data["consumer_secret"])
    app = Twitter(auth=app_auth)

    # 画像をつぶやく
    with open("001.jpg", "rb") as image_f:
        image_data = image_f.read()

    t_up = Twitter(domain="upload.twitter.com", auth=app_auth)
    id_img = t_up.media.upload(media=image_data)["media_id_string"]

    app.statuses.update(status="画像アップロードテスト", media_ids=id_img)

    print("Success!!")

if __name__ == "__main__":
    main()

Twitterクラスのdomain引数に"upload.twitter.com"を指定して新しく画像アップロード用のインスタンスを作成するみたいです。

さて、実行してみると・・・
f:id:TomoProg:20160218002434j:plain

画像が投稿できました!!

今日の成果

  • 百人一首の画像ファイルは全部ゲット出来た!!
  • Twitterに画像を投稿することが出来た!!


さて、今日はこの辺で終わりにします。
パート2を乞うご期待!!
それではまた。

TomoProg

GitHub
TomoProg (TomoProg) · GitHub

Twitter
TomoProg (@tomoprog_xxx) | Twitter

COMポートって何!?

皆さん
こんにちは、こんばんは
TomoProgです。

このブログのPVが今月100を超えたという嬉しいお知らせが来ました!!
これって自分が見た回数とかも数えられるんですかね?

何はともあれ嬉しいことです!!
見ていただいた方ありがとうございます!!
これを糧に今後も頑張って書いていこうと思います!!

さてさて、今日は仕事中にCOMポートと言う言葉が出てきたので「COMポート」について調べてみました。

COMポートって何!?

早速google先生に聞いてみるとIT用語辞典を勧めてくれました。
e-words.jp

「〜など。」や「〜を指すこともある。」など、IT用語って結構あやふやなのが多いと思うんです!!

IT用語辞典では私にはよく分からない!!

ということで、他に調べてみると以下のサイトにこんなことが書いてありました。

ウィンドウズパソコンの場合、普通はシリアルポート(RS-232C)のことだと思っていい。以前のマッキントッシュでは、モデムポートやプリンタポートがCOMポート(コムポート)になることもあった。
引用元:http://www.nttpc.co.jp/yougo/COM%E3%83%9D%E3%83%BC%E3%83%88.html

COMポートはWindowsパソコンの場合シリアルポートのことだと思っていいみたいです。

じゃあシリアルポートって何!?

シリアルポートと思っていいみたいなので、シリアルポートについて調べてみました。
Wikipediaによると

シリアルポートとは、情報を(パラレルポートとは異なり)1度に1ビットずつ送受信するシリアル通信物理インタフェースである[1]。パーソナルコンピュータの歴史の大半において、データはシリアルポートを通じてモデム、端末、その他様々な周辺装置のデバイスに伝送された。
引用元:シリアルポート - Wikipedia

シリアルポートはモデムや端末などと通信するために使われているんですね。

調べてみると結構古い規格のようで、今では過去の遺産と書いているページも見つけました。
普通のPC同士の通信には今はほぼ使われていないみたいです。
シリアルポートに変わるUSBなどの規格が出てきてから、そちらに置き換わっていったみたいですね。

PLC(シーケンサ)などの制御機器との通信ではまだまだ現役みたいです。

正直、通信すると言われればLANケーブルをハブに挿して通信するんじゃないの?と思ってしまうんですよね・・・
シリアルポートにケーブル挿して通信したという記憶がないです。

まとめ

  • COMポートと言われればシリアルポートのこと!!
  • シリアルポートは制御機器との通信ではまだまだ一般的に使用されている!!


今日はCOMポートを自分なりに調べてみました。
それではまた。

TomoProg

GitHub
TomoProg (TomoProg) · GitHub


Twitter
TomoProg (@tomoprog_xxx) | Twitter

Python使ってつぶやいてみた

皆さん
こんにちは、こんばんは
TomoProgです。

今日はPythonを使ってツイッターにつぶやいてみたので、やり方など書いていこうと思います。
(ここではPython3を使用することを前提として書きます。)

Twitterアプリを作成する

まずはPythonからつぶやくアカウントを作成します。
アカウントの作成方法は普通にアカウントを作るのと何も変わらないのでここでは省略です。

アカウントを作成し終わったら、下記のTwitter開発者用ページにアクセスし、先ほど作成したアカウントでログインします。
https://dev.twitter.com/

開発者用ページの一番下にある「Manage Your Apps」からアプリ管理画面に移動し、アプリを作成します。

アプリを作成すると、以下の4つのキーが生成されるので、メモしておきましょう。

  • Consumer Key
  • Consumer Secret
  • Access Token
  • Access Token Secret

ここまで出来れば準備完了です。

Pythonでつぶやくコードを書く

それではPythonのコードを書いていきましょう。
まず、pipを使ってtwitterモジュールをインストールします。

$ pip install twitter

インストールが出来たらコードを書いていきましょう!!

#-*- coding:utf-8 -*-

from twitter import *

api = Twitter(
    auth = OAuth(
        Access Token, 
        Access Token Secret,
        Consumer Key, 
        Consumer Secret))

api.statuses.update(status="Hello World!!")

OAuthに渡す引数はアプリを作成したときに生成された4つのキーをそれぞれ書き込みます。
api.statuses.updateのstatus引数に渡した文字列がTwitterTweetされます。
たったこれだけです。

実際に実行してみる

さてそれでは実行してみましょう!!
実行すると...
f:id:TomoProg:20160214170521j:plain
Hello World!!」がつぶやけました!!

というわけで、今日はPythonプログラムからTweetしてみました。
せっかくPython使ってつぶやけたのでボットでも作ってみようかなと思います。
それではまた。

TomoProg

GitHub
https://github.com/TomoProg

Twitter
TomoProg (@tomoprog_xxx) | Twitter