Tag Archives: python

[メモ] SlackとMattermostそれぞれのincomingWebhookへのポスト方法の違い

Pocket

MattermostはSlackのクローンであるが、incomingWebhookへのポストだけは、どうも違いがあるようだ。
以下にSlack/Mattermostそれぞれでの実例を示す。
まずmattermost

# mattermost

import requests

incomWebHook = 'http://192.168.10.1/hooks/xxxxx'
msg = 'test message'
icon_url = 'http://192.168.10.10/graphix/robot.png'
username = 'bot'

def sendMsg(incomWebHook, icon_url, username, msg):
    payload = {
            'text': msg,
            'icon_url': icon_url,
            'username': username}

    r = requests.post(
        incomWebHook,
        json=payload)

    return r

r = sendMsg(incomWebHook, icon_url, username, msg)

Slack

# slack
import requests

incomWebHook ="https://slack.com/api/chat.postMessage"
msg = 'test message'
username = 'bot'
token = "xoxb-xxxx-xxxx"

def sendMsg(incomWebHook, token, username, msg):
    payload_dic = {
            "token": token
            "type": "message",
            "channel": "#general",
            "text": msg,
            "username": username,
            "icon_emoji": ":bird:",
            }

    headers = {
            'Content-type': 'application/json',
            'Accept': 'text/plain'
            }

    r = requests.post(
            incomWebHook,
            params=payload_dic,
            headers=headers)

    return r

r = sendMsg(incomWebHook, token, username, msg)

[メモ][Python] AnacondaをWindows xpにインストールしようとすると失敗する

Pocket

Anacondaは、Pythonのほかに、IPython、Spyder、pandas他便利ライブラリが一式でついてくるお手軽Python環境である。

しかしAnacondaをWindows xpにインストールしようとすると失敗する。
具体的には、インストール途中の「メニューを作る」ステップで失敗。
無視して進めると、C:\Anaconda3に実行ファイルは揃っているので、「なんだ気のせいか」と安心して起動しようとすると「有効なWin32アプリケーションではありません」という旨のエラーが発生する。

原因は、最新版がxpに対応していないせい。
以下から2.2.0をダウンロードし、インストールする。

https://repo.continuum.io/archive/

念のためファイル名とハッシュ値も残す。

Anaconda3-2.2.0-Windows-x86.exe
7c49a4e76e1c383038c4a1e8c4ac506f

Anaconda-2.2.0-Windows-x86.exe
32246b48658d4c3faeef425cec64a131

AnacondaのFAQにしっかり記載がある。

https://docs.continuum.io/anaconda/faq

How can I use Anaconda on Windows XP?
Windows XP is supported on Anaconda versions 2.2 and earlier. Download it from our archive.

Slack/MattermostのbotをPythonのFlaskで作ろう

Pocket

Slack/Mattermost(以降、まとめてSlack)のbotといえばHubotが有名だ。
Hubotはcoffeescriptで書かれているのだが、botのためだけに新しい言語を覚えるのも面倒。
加えてHubotを動作させるにはnpmが必要。
ちょっとそこまでは…。
Pythonなら普段使いで最初から環境は作ってあるし、楽だし。
そう思っていろいろと調べてみた。

Slackのbotに必要なことは?

Slackのbotに必要なのは、端的に以下の二つ。
1. Slackからのデータ送信を受ける。
2. Slackへ何かをする。

1.は、HTTP POSTでやってくるので、POSTを受けることさえできればよい。
2.は、例えばSlack上で何かの発言をすることだが、こちらはcurl(Pythonならrequests)でも使えば簡単にできる。

PythonでHTTP POSTを受けるには?

Flaskである。
Flaskとはごくごく軽量なwebフレームワークである。
驚くくらい簡単にwebサーバを作ることができる。
もちろんPOSTを受けるのもすぐにできる。
以下、説明。

Flaskのインストール

pipでもなんでも、好きなものを使ってインストールせい。

Flaskのテスト

以下のようなスクリプトを書く。
適当な名前で保存する。
flask.pyとかはやめようね。

#!/usr/local/bin/python

from flask import Flask

app = Flask(__name__)

@app.route('/')
def welcome():
    html = '<html><title>welcome</title>'
    html = html + '<body>welcome</body></html>'
    return html

if __name__ == '__main__':
    app.debug = True
    app.run(host='0.0.0.0')

上記のapp.route(‘/’)とは、ルーティング。
ルートディレクトリ(’/’)へのアクセスがあったら、次のdef welcome()が(デコレートによって)呼ばれる、ということである。

上記の場合、welcomeと表示するhtmlが返る。

app.debug = Trueについては後述。
app.run(host=’0.0.0.0)のhost=…の記述により、サーバを外部に公開することになる。

テストスクリプトの実行

$ python ./flasktest.py
 * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
 * Restarting with stat
 * Debugger is active!
 * Debugger pin code: 213-546-048

localhostのポート5000でサーバが立ち上がったと分かる。
ブラウザでアクセスして「welcome」と表示されればよい。

ところで、app.debut = Trueだが、スクリプトを書き換えると、自動的に再読み込みをしてくれる。
実際のログは以下。

 * Detected change in '/usr/home/doe/py/flasktest.py', reloading
 * Restarting with stat
 * Debugger is active!

激烈に便利な機能なので、開発中は有効にしておくこと。

SlackからのPOSTを受ける。

先ほどのスクリプト冒頭のimportを以下のように変更。

from flask import Flask, request

さらに以下を追加。

@app.route('/matter', methods=['POST'])
def post():
    print request.form

上記のようにしておいて、Slack側のOutgoing Webhookで、呼び出すURLに「http://<あなたのサーバのアドレス>:5000/matter」を指定する。

Slack側からwebhookを呼び出してみると、POSTされた内容がログに表示されるはず。
なお、def post()が何も返さないのでエラーは出るが気にしない。

以下が例。

ImmutableMultiDict([('user_id', u'xxxxx'), ('channel_id', u'xxxxx'), ('timestamp', u'1414562326'), ('team_id', u'xxxx'), ('trigger_word', u'test'), ('channel_name', u'off-topic'), ('token', u'xxxtokenxxx'), ('text', u'test'), ('team_domain', u'xxxx'), ('user_name', u'xxxx')])

つまりPOSTの内容はディクショナリになっている。

Slackへ応答を返そう

Slackへ応答を返す場合には、POSTでもらった中にあるtokenが必要である。
応答文、tokenのディクショナリを作っておいて、それをjsonに変換し、返してやればよい。
Mattermostの場合、tokenのキーは’MATTERMOST_TOKEN’

先ほどのスクリプトを最終的に以下のようにする。
(わざわざjsonをimportしているが、Flaskにもそういう機能がある気がしてならない)
これでSlackから通知を受けると、「You said <トリガーワード>」という応答がSlackへ帰る。

#!/usr/local/bin/python

from flask import Flask, request
import requests
import json

app = Flask(__name__)

@app.route('/')
def welcome():
    html = '<html><title>welcome</title>'
    html = html + '<body>welcome</body></html>'
    return html

@app.route('/matter', methods=['POST'])
def post():
    postdic = request.form
    incomeText = postdic['text']
    token = postdic['token']
    text = 'You said ' + incomeText

    payload = {
            'text': text,
            'MATTERMOST_TOKEN': token}
    json_payload = json.dumps(payload)
    return json_payload

if __name__ == '__main__':
    app.debug = True
    app.run(host='0.0.0.0')

あとはどんどん膨らませていけばよい。

 

[Python] listの差分を知るには

Pocket

Pythonで、二つのリストの差分を知るには。
リストのままでは引き算ができない。
set()でset型にしてから引き算をする。
ただしset()すると、与えられたリストから重複した要素が除かれること、順序も保持されないことに注意
また、set()して要素を操作した結果はset型のまま。
list()でリストに戻す必要がある。

以下、サンプル。

>>> a = ["a"]
>>> b = ["b","c","d"]
>>> b - a
Traceback (most recent call last):
  File "", line 1, in 
TypeError: unsupported operand type(s) for -: 'list' and 'list'
>>> c = list(set(b) - set(a))
>>> c
['c', 'b', 'd']
>>> c.sort()
>>> c
['b', 'c', 'd']

[Python][memo] タイムスタンプの差を求める

Pocket

すぐ忘れるのでメモ。

文字列としてのタイムスタンプは、datetime.datetime.strptimeで、フォーマットを指定してdatetime.datetime型に変換。
そうしたら加減算ができる。datetime.timeでは出来ないので注意。
以下、IPythonでの例。

In [1]: from datetime import datetime

In [2]: t1 = datetime.strptime("14:36:02.0689", "%H:%M:%S.%f")

In [3]: t2 = datetime.strptime("14:36:03.0102", "%H:%M:%S.%f")

In [4]: print type(t1)


In [5]: delta = t2 - t1

In [6]: print str(delta)
0:00:00.941300

In [7]: print str(delta)[6:]
0.941300

In [8]: 

[Python] requestsとlxmlで京急の運行情報を抽出しよう

Pocket

botに京急の運行情報を調べさせて、Slackで発言させたい。
使用言語はPython。
さあどうしようかと思ったら、さいきんは、どんなものでもライブラリが揃っていて、あっという間になんでも出来てしまうのな。

ページの取得はrequests、解析はlxmlを使う。

Webページの事前解析

ページのソースから、狙いの箇所を特定するようなキーワードを見つける。
あるいは、たとえばChromeなら、デベロッパーツールで探してもよい。
京急のページであれば、以下のように。

keikyuanalyze
手がかりは”div.unko-panel”。
これをもとにコードを書く。

抽出コード

stackoverflowを調べればサンプルコードなんかいくらでもあるよねー。

import lxml.html
import requests

def getKeikyuStatus():
    target_url = "http://unkou.keikyu.co.jp/"
    target_html = requests.get(target_url).text
    root = lxml.html.fromstring(target_html)

    divs = root.xpath("//div[contains(@class, 'unko-panel')]")
    for div in divs:
        unkouinfo = div.text_content().encode("UTF-8")

    return unkouinfo.strip()

requestsでwebページ取得。
lxmlで読み込んで、class “unko-panel”のdivタグを見つければよい。

[参考]slackへの投稿

ここはサラッと。
詳細はslackのサイトを見る。
前章の関数の戻り値を引数に取る関数。

def noticeSlack(keikyuStatus):
    url ="https://slack.com/api/chat.postMessage"
    msg = keikyuStatus + " #keikyu"

    payload_dic = {
        "token": "xoxb-xxxx-xxxx",
        "type": "message",
        "channel":"#general",
        "text":msg,
        "username":"keikyubot",
        "icon_emoji":":bird:",
        }

    headers = {'Content-type': 'application/json', 'Accept': 'text/plain'}
    r = requests.post(url, params=payload_dic, headers=headers)

    return r

[Python] wxPythonで、タイトルバーにアイコンを表示するには

Pocket

Pythonからpy2exeなどでWindowsアプリケーションを作成したときに、アイコンを設定することができる。
しかし、作成したアプリケーションがGUI版の場合、GUIタイトルバーのアイコンを設定するには、ちょっとしたテクニックが必要である。
py2exe等でアイコン設定済み、かつGUIはwxPythonで作成している前提で、その方法を示す。

サンプル

class MyFrame(wx.Frame):
    def __init__(self, *args, **kwds):
	(略)
		if os.path.exists("myWxApp.exe"):
    		self.SetIcon(wx.Icon("myWxApp.exe",wx.BITMAP_TYPE_ICO))

Frameクラスの初期化defの中で、上記のような記載を加える。
もちろんmyWxApp.exeは最終的なファイル名。

説明

py2exe等でiconファイルを設定するというのは、つまり実行ファイルに埋め込むということ。
上記のようにSetIconで自分自身の実行ファイルを参照すると、埋め込んでおいたアイコンファイルを読み取ることができる。

元ネタ
How to use py2exe icon_resources in wxPython application?

【参考】wxPython

http://ja.wikipedia.org/wiki/WxPython
wxPythonは、「wxPythonはPythonで記述されたクロスプラットフォームなウィジェット・ツールキットである。」
要するにPythonをGUIで動かすツールキット。OSをまたがって使用できる。

[Python][Windows] Windows7への純正Pythonインストールメモ

Pocket

ActivePython入れたり純正Python入れたり訳わかんなくなるからメモ。

Pythonのインストール

https://www.python.org/ から2.xでも3.xでもダウンロード、インストール。
アップグレードの場合は、たぶん自分で古いバージョンをアンインストールした方がよい、と思う。
pythoninstallpathadd
インストール時設定は、pythonをpathに追加するところだけ変更した。

pipのインストール

不要ッ!
2.7.9以降、あるいは3.4以降なら最初っからインストールされている。
pip included with Python
実際、デフォルトの状態で以下の通り。

C:\Users\nobwak>python --version
Python 2.7.9

C:\Users\nobwak>pip list
pip (1.5.6)
setuptools (7.0)

ん?ちょっと古いような?

pip install -U pip

などとして最新版にした。

[Python] wxGladeでGUIのデザインを

Pocket

Python、Perl、Ruby、PHPなどのLight Languageは、俺みたいな素人プログラマでもじゃんじゃんコードを書けるところが素晴らしい。
さらにそのコードがGUIで動くようになるのなら、もっと素晴らしい。
wxGladeでそれができる。wxGladeでGUIを作ってみたので記す。

wxGladeとは

http://wxglade.sourceforge.net/index.php
wxPython向けのGUIデザイナーである。
wxPythonとはPythonのGUIツールキット。
また、GNOMEのGUIツールキットであるGladeが名前に入っている通り、wxGladeの設計思想はGladeに沿っている。

インストール

こちらからどうぞ。
以下の例ではWindowsを使っている。

最初の一歩

どんなGUIを作るにしても、まず最初にすべきことがある。

起動すると以下のような画面。
wxpyatstart
何のとっかかりもなく、いきなり途方に暮れるわけだが、慌てず騒がず、左上ウインドウのさらに左上にあるアイコンをクリック。
wxpyaddflame
そのままOK。
wxpyMyframe
wxpyaddframedone
なんか枠ができた。
wxpyframewin
そしてこちらを選んで、先ほどの枠に追加。
wxpaneladd
するとこのようなのっぺりした画面に。
basepanel01
あとは分かりやすいように名前を変更。
rootpanel
これで最初の一歩が終了。
ここから、作りたいGUIに合わせて作業をしていく。

作業の前に(日本語は使わないでおこう…)

超絶分かりやすいPythonにも弱点がある。
それは文字コードの扱い。
wxGladeで日本語を書き込むことはできるが、UTF-8なのかShift-JIS(CP932)なのかの扱いが大変に面倒である。
だから、GUI作成時のテキスト、注釈、ボタンは適当な英語で書いておき、実際の処理を書くときに日本語に変えるのがよいと思う。

画面の分割と配置

最終的に以下のようなGUIを作りたいとする。
wxpylast
このGUIは、まず画面を縦に三分割する。さらに1行目、3行目を横に三分割する。
分割にはパレット上の以下のツールで行う。
wxpybunkatsu
ざくざくと分割して以下のように。
wxpyseparate
以下のように便宜的に番号を振って、
wxpynumbers
①にはテキストを、②にはテキストの枠を、③にはボタン、④には横棒、⑤にはスペース、⑥、⑦にはボタンを置く。
wxpyzakkuri
ツリーはこんなかんじ。
wxpyhidarigawa
名前を変更し、空白(スペーサー)は適当に横に伸ばす。
あとは、経験上、各要素を以下のようにするといいかも。
wxpybityousei
wxpylast

書き出し

wxpyapp
Appのプロパティから、LanguageにPython、Output Pathでファイルを指定し、Generate Codeでコード生成。

以下が例。

#!/usr/bin/env python
# -*- coding: CP932 -*-
#
# generated by wxGlade 0.6.8 (standalone edition) on Sun Dec 28 07:13:39 2014
#

import wx

# begin wxGlade: dependencies
import gettext
# end wxGlade

# begin wxGlade: extracode
# end wxGlade


class MyFrame(wx.Frame):
    def __init__(self, *args, **kwds):
        # begin wxGlade: MyFrame.__init__
        kwds["style"] = wx.DEFAULT_FRAME_STYLE
        wx.Frame.__init__(self, *args, **kwds)
        self.panel_1 = wx.Panel(self, wx.ID_ANY)
        self.label_1 = wx.StaticText(self.panel_1, wx.ID_ANY, _("input : "))
        self.inputfile = wx.TextCtrl(self.panel_1, wx.ID_ANY, "")
        self.ChooseButton = wx.Button(self.panel_1, wx.ID_ANY, _("Choose"))
        self.static_line_1 = wx.StaticLine(self.panel_1, wx.ID_ANY)
        self.go = wx.Button(self.panel_1, wx.ID_ANY, _("Run"))
        self.exit = wx.Button(self.panel_1, wx.ID_ANY, _("Cancel"))

        self.__set_properties()
        self.__do_layout()

        self.Bind(wx.EVT_BUTTON, self.choosefile, self.ChooseButton)
        self.Bind(wx.EVT_BUTTON, self.goclicked, self.go)
        self.Bind(wx.EVT_BUTTON, self.exitclicked, self.exit)
        # end wxGlade

    def __set_properties(self):
        # begin wxGlade: MyFrame.__set_properties
        self.SetTitle(_("frame_1"))
        self.ChooseButton.SetToolTipString(_("choose a file "))
        # end wxGlade

    def __do_layout(self):
        # begin wxGlade: MyFrame.__do_layout
        sizer_1 = wx.BoxSizer(wx.VERTICAL)
        sizer_2 = wx.BoxSizer(wx.VERTICAL)
        sizer_4 = wx.BoxSizer(wx.HORIZONTAL)
        sizer_3 = wx.BoxSizer(wx.HORIZONTAL)
        sizer_3.Add(self.label_1, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5)
        sizer_3.Add(self.inputfile, 1, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5)
        sizer_3.Add(self.ChooseButton, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5)
        sizer_2.Add(sizer_3, 1, wx.EXPAND, 5)
        sizer_2.Add(self.static_line_1, 0, wx.EXPAND, 5)
        sizer_4.Add((200, 20), 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5)
        sizer_4.Add(self.go, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5)
        sizer_4.Add(self.exit, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5)
        sizer_2.Add(sizer_4, 1, wx.EXPAND, 0)
        self.panel_1.SetSizer(sizer_2)
        sizer_1.Add(self.panel_1, 1, wx.EXPAND, 0)
        self.SetSizer(sizer_1)
        sizer_1.Fit(self)
        self.Layout()
        # end wxGlade

    def choosefile(self, event):  # wxGlade: MyFrame.
        print "Event handler 'choosefile' not implemented!"
        event.Skip()

    def goclicked(self, event):  # wxGlade: MyFrame.
        print "Event handler 'goclicked' not implemented!"
        event.Skip()

    def exitclicked(self, event):  # wxGlade: MyFrame.
        print "Event handler 'exitclicked' not implemented!"
        event.Skip()

# end of class MyFrame
if __name__ == "__main__":
    gettext.install("app") # replace with the appropriate catalog name

    app = wx.PySimpleApp(0)
    wx.InitAllImageHandlers()
    frame_1 = MyFrame(None, wx.ID_ANY, "")
    app.SetTopWindow(frame_1)
    frame_1.Show()
    app.MainLoop()

[Python] pyInstallerの遅さにがっかりしてpy2exeにしたら爆速で驚いた件

Pocket

自作PythonスクリプトをWindows実行バイナリに変換する場合、pyInstallerはとっても楽ちんなのであるが、問題もある。
実行ファイルがスタートされるまで、とても待たされることだ。

その遅さに耐えかねてpy2exeを試してみたところ、ビルドまでは面倒なものの、作成した実行ファイルはめっぽう速くて驚いた。
そういったわけで、py2exeでのWindows実行バイナリ作成方法について記す。

まず最初に、pyInstallerとpy2exeで果たしてどの程度差があるかを示す。

実行速度の違い

UNIX系だと、time; <実行ファイル> とすると所要時間を計測してくれるが、Windowsだとどのようにするのであろうか。
よく分からない。
あんまり興味もないのでWindowsにもあるtimeコマンドで大まかに測ってみた。

前提
・同じスクリプトを使用する
・バイナリは一つにまとめる
・バイナリの処理完了までを測る

結果
・pyInstallerだと5秒
・py2exeだと2秒

その差3秒。
たかだか3MBytesのプログラムでこの違いである。
ただ、py2exeを避けていたのには理由がある。

py2exeの制限

py2exeはバイナリ作成のために、別にsetup.pyを書かねばならない。
対するpyInstallerは、pyInstaller本体に自作スクリプトを引数として与えればいいだけ。こちらからすると面倒ではある。
また、pyInstallerを使っていた時には、特に意識しなかったMSVCR90.dllの考慮もしなければならない。
さらにさらに、エンコーディングにも注意が必要(後述)。

が、これだけの弱点を差し引いても起動時間の差は魅力。
くわえて、setup.pyは一度書いてしまえば使い回しもできるんである。
というわけで、py2exeに宗旨替えを決意した。

py2exe: インストール

http://www.py2exe.org/ から。
ActivePythonであれば、pypm install py2exeでインストールできる。

py2exe: MSVCR90.dllの準備

py2exeでのバイナリ作成、およびバイナリの実行にはMSVCR90.dllが必要。

MSVCR90.dllはファイル名が同じでも複数バージョンが存在する。
悪いことにpy2exeは特定のバージョンを要求する。
そのバージョンが9.0.21022.8。
VisualStudioであれば「SP1でない」2008、あるいはこちらも「SP1でない」Microsoft Visual C++ 2008 Redistributable Package に含まれている。

x86向け
http://www.microsoft.com/ja-JP/download/details.aspx?id=29
x64向け
http://www.microsoft.com/ja-JP/download/details.aspx?id=15336

以下はあくまで参考
x86向けSP1
http://www.microsoft.com/ja-JP/download/details.aspx?id=5582
x64向けSP1
http://www.microsoft.com/ja-JP/download/details.aspx?id=2092

MSVCR90.dll、Microsoft Visual C++ 2008 Redistributable Packageのインストーラ(vcredist_x86.exe)ともに、プロパティからバージョンを確認することができる。

バイナリ作成者がDLL再配布の権利を持っている場合、DLLも含めて自作プログラムを配布できる。
権利がなければ、ユーザには上記のMicrosoft Visual C++ 2008 Redistributable Packageをインストールしてもらうこと。

py2exe:setup.pyって何よ。

py2exeは、バイナリ化じたいの処理を、pythonスクリプトで書く。
自作スクリプトのほかに、setup.pyを書く必要があるのはそのため。

py2exe: setup.pyの書きかた

http://www.py2exe.org/index.cgi/Tutorial

上記チュートリアルに沿って進める。

以下の通りのsetup.pyを作る。
ひとまず自作スクリプトと同じディレクトリが良いでしょう。
もちろん、jisaku.pyは自作スクリプト名に変更。

from distutils.core import setup
import py2exe

setup(console=['jisaku.py'])

そうしたら、setup.py, 自作スクリプトのあるディレクトリで、以下のように実行するだけ。

python setup.py py2exe

そうすると、同じディレクトリにdistというディレクトリが作られ、その下に実行ファイルができあがる。
簡単である。

あとはこのsetup.pyをベースに、いろいろと加えていけばよい。
py2exeのオプションは以下を参照のこと。
http://www.py2exe.org/index.cgi/ListOfOptions

python setup.py py2exeとタイプするのが面倒

sys.argv.append(‘py2exe’)を加えてあげれば、それ以降”python setup.py”だけでよくなる。

from distutils.core import setup
import py2exe, sys, os

sys.argv.append('py2exe')

setup(console=['jisaku.py'])

 

実行ファイルを一つにまとめるには

http://www.py2exe.org/index.cgi/SingleFileExecutable

前章で作成したsetup.pyをベースに、といいつつガラッと変わる。
とはいえ、基本的な書式は変わっていない。

from distutils.core import setup
import py2exe, sys, os

sys.argv.append('py2exe')

setup(
	options = {'py2exe': {'bundle_files':1}},
	zipfile = None,
	console = [{'script': "jisaku.py"}]
)

bundle_filesでファイルのまとめ方を指定する。
値は1でよい。
1は、とにかく一つにまとめる。
2だと、本体とPython.dllが分かれる。
zipfileもNoneでよい。
ここにファイル名を指定すると、各種DLLがそのファイル名でzipされる。
Noneであれば本体にマージされる。

本体を圧縮するには

速度でpy2exeを選択した私としては、あまり使おうという気にならないのだが。
手元の自作スクリプトから作成した5MBの実行バイナリが3.5MBになった。

from distutils.core import setup
import py2exe, sys, os

sys.argv.append('py2exe')

setup(
	options = {'py2exe': {'bundle_files':1, 'compressed': True}},
	zipfile = None,
	console = [{'script': "jisaku.py"}]
)

 

アイコンを追加するには

icon_resourcesで指定する。
http://www.py2exe.org/index.cgi/CustomIcons

from distutils.core import setup
import py2exe, sys


sys.argv.append('py2exe')

setup(
	options = {'py2exe': {'bundle_files':1}},
	zipfile = None,
	console = [{
			'script': "jisaku.py",
			'icon_resources': [(1, "jisaku.ico")]
			,}]
)

 

実行時にコマンドプロンプトウインドウを開かないようにするには

consoleではなくwindowsにする。

from distutils.core import setup
import py2exe, sys


sys.argv.append('py2exe')

setup(
	options = {'py2exe': {'bundle_files':1}},
	zipfile = None,
	windows = [{
			'script': "tsuboneChecker.py",
			'icon_resources': [(1, "Artcore-Illustrations-Artcore-4-Terminal.ico")]
			,}]
)

 

py2exeでのエンコーディング

py2exeでホクホクしていたら、スクリプトの実行は問題ないのに、ひとたびpy2exeでバイナリにすると、途端にエンコーディングエラーが出る、という症状に悩まされた。
結論としては、以下を加えれば解決。

if hasattr(sys, 'setdefaultencoding'):
    import locale
    lang, enc = locale.getdefaultlocale()
    sys.setdefaultencoding(enc or 'cp932')
    del sys.setdefaultencoding

http://www.py2exe.org/index.cgi/EvenMoreEncodings
http://d.hatena.ne.jp/shive/20110626/1309061690