fc2ブログ

ぽよメモ

ぷよぐやみんぐ

CATEGORY

  • このページのトップへ

.vimrc


新学期始まって完全に忘却の彼方に押しやってしまう前にvimの設定を残しておきたいと思います。

といってもこれ貼るだけですが…

細かいコト省いて要点だけまとめると、
1. パッケージ管理はNeoBundle
多分殆どの人はこれなのでは?必要なくなったプラグインは削除してから:NeoBundleCleanして消しましょう。プラグインのアップデートは:NeoBundleUpdate

2. pyenvにパスを通すこと
vimが+python/+python3かつ+luaとかでコンパイルされているのが望ましいです。MacはMacVim-Kaoriyaを使えばよいかと。Ubuntu等ではえ?君せっかく Python のバージョン管理に pyenv 使ってるのに Vim の補完はシステムライブラリ参照してるの?を参考にがんばってください。

3. jediとneocompleteの設定をうまく書いて競合させないようにすること
*.pyのときの処理を変えることで上手くできます。→ここ参照[vim]python補完プラグイン「jedi-vim」を快適にする方法(jedi-vim+neocomplete)

4. LightlineにSyntaxErrorなどを表示させる
作者が教える! lightline.vimの導入・設定方法! 〜 初級編 - インストールしよう
作者が教える! lightline.vimの設定方法! 〜 中級編 - 展開コンポーネントを理解しよう
この2つを見てそのままコピペするだけです。むずかしいこと考えるのはやめました。

5. jediやflake8などをきっちりとpipで導入しておくこと
jedi-vimに必要なjediやsyntasticで使っているflake8はpip installで導入することができます。普通にgit cloneしてpyenvを入れた人はpipが元から入っているので、それを使うと~/.pyenv/shims以下にこれらが展開されます。また、パスもそこに通っているので普通に動く…はずです(割と動かなくて困ることがある

6. vim-autocloseとtcomment_vimは相当便利なので推奨
面倒な作業が減ります


pythonしか今のところかく予定がないのでこう言った感じの.vimrcになりました…まだまだ使いこなせてないので精進します…
スポンサーサイト



カテゴリー:ぷよぐやみんぐ


sudoとpyenv


さっきの記事「RasPiで室温を計測する」の最後に書きましたが、通常pyenvを使っている人の環境ではシステム側のpythonと、pyenv側のpythonが入っていると思います。

このとき何もせずpyenvをインストールしていると
$ sudo python hoge.py
したとき、勝手にシステム側のpythonが呼ばれてしまいます。

sudoしたときにどうやってpyenv側のpythonを呼び出すかですが、/etc/sudoersのDefaultにpyenvディレクトリのパスを追加してやることで可能になります。

su -してrootにログインしてから以下の操作を行ってください。
$ vim /etc/sudoers

#初期 Default secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
#/home/pi/.pyenv/shims:/home/pi/.pyenv/bin:を追記
Default secure_path="/home/pi/.pyenv/shims:/home/pi/.pyenv/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
保存時に怒られます。:wq!しましょう。

これでひとまずsudo pythonしたときにpyenv側から呼びだされます。

しかし、python-smbusはシステム側のpythonに依存し、pyenv側に入れることができません。
試しにsudo python tmp102.pyをするとわかりますが、python-smbusはシステム側のpythonにいるので、sudoコマンドでpyenv側のpythonを呼び出してもNo module named smbusと怒られてしまいます。
そこでsmbus-cffiを使います。
$ sudo apt-get install libi2c-dev libffi-dev
$ pip install cffi
$ pip install smbus-cffi
これでもう一度試してみましょう。
$ sudo python tmp102.py
22.375
できました。

これ、システム側を完全に切り捨てて運用することが前提となっている感じがすごくアレですが…他に対処法が見つからなかったので…

カテゴリー:ぷよぐやみんぐ


rsyncでファイルを同期する


botを作るにあたり、だいたいはThinkPadに入れたUbuntuで開発を行っていたのですが、結局動作させるのはRasPiなわけで、動かしてみてうまく行かなかった時細かい修正はRasPiにsshして行っていました。

するとRasPi側と開発環境側で齟齬が発生するようになってしまい、ちょっとややこしいことに。
そこでスクリプトが入っているフォルダごと同期してしまおうということになりました。

Linuxにはこういうとき超便利なrsyncというコマンドが用意されています。最高。
RasPiへのアクセスにはsshを用いてログインしrsyncを使うので、まずはsshの設定をします(省略)

-eを使うなど古い書き方になってしまいますがこれが普通です。
rsync -au -e "ssh -p 22 -i ~/.ssh/id_rsa" pi@192.168.10.50:/home/pi/bot ~/


-aは「元のパーミッションやグループなどを保持したまま同期(-rlptgoDと同義)」、-uは「追加されたファイルだけをコピー」、-eは「リモートシェルの指定(最近はsshがデフォらしいので指定しないで良い?)」です。
しかしシェルスクリプト内での rsync に ssh 鍵を指定するに書いてあるように、シェルスクリプト内では”ssh (以下略)”の部分は読み取ってもらえません。
つまりcronで定期的に回すなどの実装にはこのままでは不適だということです。

なので.bashrcにRSYNC_RSHという環境変数を設定します。
RSYNC_RSH="ssh -p 22 -i $HOME/.ssh/id_rsa"
あとはsource ~/.bashrcして、普通にrsyncします。
rsync -au pi@192.168.10.50:/home/pi/bot ~/

また、sshに公開鍵暗号を使う今回のような場合、cronを使って定期的に回したければ公開鍵と秘密鍵を作る際にパスをかけないようにしておく必要があります。

あとはこれを適当なファイルに書いて「〜〜.sh」といった感じで書き、適当にcronに投げればオッケーです。
今回はリモートフォルダからローカルに保存するように書きましたが逆も可能です。また、リモート↔ローカルだけでなく、ローカル↔ローカルやリモート↔リモートも可能です。

このとき注意するのはソースとなるディレクトリのパスの最後に/を入れるかどうかです。
#ディレクトリごと同期
rsync -au /path/to/remote /path/to/local

#ディレクトリ以下の内容のみ同期
rsync -au /path/to/remote/ /path/to/local
つまり最後に「/」をつけなければリモートにある「A」というディレクトリをローカルにある「B」を指定してrsyncしたとき、Bの中にAというディレクトリが出来ます。「/」をつけると、「A」というディレクトリの中身が「B」に展開されます。
これにさえ注意を払っておけば問題ないと思います。

その他のオプションについてはググればすぐに出てくると思いますので省略。場合によって--excludeや--deleteを上手く使えばかなり高度なファイル同期/バックアップとして使えると思います。

カテゴリー:ぷよぐやみんぐ


tweepyを使って指定条件のツイートを削除


この前はrequestsとrequests-oauthlibを使ってpythonでツイートをしました。ツイートするだけなら楽勝なんですが、さすがにTLを取得してゴニョゴニョとかはなんかもう闇っぽかったのでtweepyを使ってみることにしました。
pip install tweepy
準備は完了です。
import tweepy

CK = 'xxxxxxxxxxxxxxxx'
CS = 'xxxxxxxxxxxxxxxxxxxxxxxxx'
AT = 'xxxxxxxxxxxxxxxxx'
AS = 'xxxxxxxxxxxxxxxxxxxxxxxxx'

auth = tweepy.OAuthHandler(CK, CS)
auth.set_access_token(AT, AS)

api = tweepy.API(auth)

#アカウントの情報を取得
myinfo = api.me()
#100ツイートほどTLを取得
tweets = tweepy.Cursor(api.user_timeline, id = myinfo.id).items(100)
TLを取得までいけました。このままprint tweetsすればそれはもう意味不明な文字列がたくさん表示されることでしょう。

上で示したように、myinfoというオブジェクトにはたくさんのデータが格納されています。同様に取得した情報にもたくさん情報が入っており、tweepyのAPIリファレンスを見てもさっぱり書いてないのでつらいんですが、Twitter DeveloppersのAPIリファレンスを読むと多少はわかるかと。例えば
#リストで返ってくるTLをforループにかける
for tweet in tweets:
#本文を取得
sentence = tweet.text #Twitter始めました

#ツイートのidを取得
id = tweet.id #145872304857203445452345(適当な数字です

#fav数、RT数を取得
rt_ct = tweet.retweet_count #0
fav_ct = tweet.favorite_count #1

#ツイートした人の名前及びID
name = tweet.user.name #ぷりん
sc_name = tweet.user.screen_name #pudding_info

#公式アカウントかどうか
kousiki = tweet.user.verified #False

#ツイート日時
date = tweet.created_at #2015-09-17 16:55:59

#via名
via = tweet.source #Twitter for iPhone
print type()すると各要素がどういう値かわかると思いますが、nameやtextはunicode、verifiedはboolean、日時はdatetime.datetime、RT数やfav数はintで返ってきます。
公式のリファレンスを読むとRT数はretweet_countなのにfav数はfavorites_countだとか、いやなんでやねんみたいなとこがたまにあって面白いです(全然読みたいとは思いませんが

休講通知botには、毎朝その日の休講情報をダイジェストでツイートする機能を実装したかったのですが、ただそれを実装するだけではどんどんダイジェストツイートが溜まっていってウザいなぁと思ったので、毎回それと一緒に前の日のダイジェストツイートを削除してやろうと言うわけで、TLを取得までした後、以下の様な実装を加えました。
ダイジェストツイートは「2015/9/28 本日の休講はありません」といった感じの仕様にしてあります。
import re
from datetime import datetime, timedelta

#前日の日付を取得
d = datetime.now() + timedelta(days = -1)
yesterday = '%s/%s/%s' % (d.year, d.month, d.day)

#本文に一致するものを探し、削除
for tweet in tweets:
r = re.compile(yesterday)
sentence = tweet.text.encode('utf-8')
m = re.match(r, sentence)
if m == None:
pass
else:
api.destroy_status(tweet.id)
実装してから正規表現である必要なくねとか思いましたがもう良いんです。

そのうちリプライに反応して休講情報とか持ってこれるようにしたいなぁ……

カテゴリー:ぷよぐやみんぐ


Pythonでツイートする


実は休講通知botは完成しました((超雑なコードで
結局本当にこれまでやって来たことを一つにまとめただけなのですが、一応動いてはいます()

今回はpythonでツイートする方法をまとめておきます。

twitterにツイートするまでにはまず「apps.twitter.com」にアクセスし、ツイートするクライアント(アプリケーション)を作成する必要があります。
これまでならすべてのアカウントで作成できたのですが、最近Twitter社のクソな仕様粋な図らいにより電話番号がひも付けされたアカウントでしかアプリケーションが作成できなくなりました。またツイート時に必要なアクセストークンはアプリケーションの作成画面から見ることができるのは、そのアプリケーションを作成したアカウントの分だけです。

当然電話番号は一つしか持っていません(大体の人はそうだと思います
メインのアカウントにひも付けされています(大体の人はそうだと思います

ど う す ん の

というわけでこういうサイトを発見しました→Twitter BOT作るときOAuthのAccess token取得するのがめんどいから簡単に取得できるwebサービスつくった
先人は偉大です。ありがたく使わせていただきました。

番号を紐付けしたアカウントでapps.twitter.comにログインしアプリケーションを作成

ログアウト後botで使うアカウントでログイン

先程のサイトを使ってアクセストークンを取得

これで使うアカウントの「Access Token(以下AT)」「Access token Secret(以下AS)」、そして作成したアプリケーションの「Consumer Key(以下CK)」「Consumer Secret(以下CS)」が揃いました。
ようやくpythonの方に入っていきます。
今回はTwitterのAPIを叩くためにOAuth認証というモノを使います。

これにはすでにライブラリが用意されており、
pip install requests
pip install requests-oauthlib
pipでインストールすることができます。

# coding: utf-8
from requests_oauthlib import OAuth1Session

CK = "xxxxxxxxxxxxxxxxxx"
CS = "xxxxxxxxxxxxxxxxxx"
AT = "xxxxxxxxxxxxxxxxxxx"
AS = "xxxxxxxxxxxxxxxxxxx"

# ツイート投稿のURL
url = "https://api.twitter.com/1.1/statuses/update.json"

def tweet(text):
# ツイート内容を以下に記述
params = {"status": text}

# OAuth認証して投稿
twitter = OAuth1Session(CK, CS, AT, AS)
req = twitter.post(url, params = params)

# 返ってくるコードを確認
if req.status_code == 200:
print ("ツイート完了")
else:
print ("ツイートできませんでした: %d" % req.status_code)

if __name__ == '__main__':
print tweet("はじめまして") #確認


提供されているAPI一覧はこのあたりを参照してください。

APIは一定時間に指定回数以上叩くとアプリケーションごと規制されてしまいます。連投は避けたほうが無難です。
本当は連投時に遅延処理を仕込んだほうが良いんですが、昨日はそれ以外の部分の実装で忙しかったので…(言い訳
そのうちやりますそのうち


カテゴリー:ぷよぐやみんぐ