dev

たくさんのdxfをillustratorで開けるように変換する

現在のIllustratorでは、AutoCAD以外から書き出したdxfを開こうとすると「テキストファイル」として認識されてしまいます。

https://helpx.adobe.com/jp/illustrator/kb/234692.html

AutoCADのheaderが無いからなのですが、せめて選択できるとか警告を出すとかにしてほしい。。。

まあ出来ないものは仕方ないとして、例えばOpenSCADやKiCADで書き出したdxfを毎度テキストエディタで開いて、上記サイトを開いてheaderをコピペして、無駄な改行を削除して。。。とやるのはさすがに極まっています。愚が。

こんなときこそautomatorの出番です。(osx限定)

automatorで「アプリケーション」を作成し、「シェルスクリプトを実行」、「引数として」入力を引き渡し、以下のコマンドを実行します:


for f in "$@"
do
	LF=$(printf '\\\012_')
	LF=${LF%_}
	sed -i "" -e "1s/^/0${LF}SECTION${LF}2${LF}HEADER${LF}9${LF}\$ACADVER${LF}1${LF}AC1008${LF}/" $f 
done

sedの挙動はLinuxのGNU版とosxのBSD版では微妙に違いがあり、下記サイトを参考にしました。

http://qiita.com/catfist/items/1156ae0c7875f61417ee

そしたら後は作成されたappをdockに追加して、headerを追加したいファイル群をアイコンにドラッグ&ドロップするだけでおkです。

個人的にosx卒業する機運が高まりつつあるなか、こういう小回りの良さが捨てがたいなぁと思います。

confluenceをmedium風のコンテンツファーストデザインにする

cssを書いた:

https://github.com/Drunkar/confluence_css_mediumlike

 

cssを適用するブラウザ拡張(たとえばchromeならstylishなど)で適用する。

※ コンテンツ内容は変わりません

デザインコンセプト

会社での情報共有ツールとしていろんなところで使われているっぽいconfluenceだが、残念なことにそのデザインはひどい:

  • 統一されていない: 場所によってavatar画像が四角だったり丸だったり。
  • メリハリにとぼしい: 見出しがはっきりと分かれてくれないので、見出しを識別する負担を見る人に強いている
  • フォントがダサい: Arialしか指定されてないので日本語は完全にOS依存
  • 意味のないリンクが多い: “Confluence”とかいらねーし。コンテンツこそが重要。

特にやりたかったことは、

  • ブログ投稿の敷居を下げる

こと。情報発信がカジュアルにできればみんな動いてる感が出て良い循環が生まれる気がする。このへんはgithubのプロファイルページの”Contribution activity”が分かりやすくて良いデザインだなーと思っていた(自分のアクティビティだけしか表示されないけど)。

なのでデザインのコンセプトは以下のとおり:

  • 記事の内容を見るためにあるので、もちろんコンテンツファースト
  • ただし記事階層へのリンクなど、情報の構造は表示する
  • 日頃から良いと思っていたMediumとGithubを参考にする
  • 文字のメリハリをはっきりつける: mediumでも弱いと思っていたので見出しの直前はさらに離す
  • 良い日本語フォントを使う: Noto sans jp

なぜコンテンツファーストか

そもそもmediumがなぜあのようにワンカラムで、記事コンテンツとシェアメニューしか表示していないのか。逆になぜ普通のブログは「人気記事」とか「最近の更新」とかブログパーツとかが表示されているのか。

答えは簡単で、前者はSNS+スマホ時代に適したデザイン、後者はPC時代のデザインだからだ。SNS以前のPC時代では検索エンジンが流入の要だったため、まさにサイトを「訪問」する感覚で人はブラウジングをしていた。そうした時代に別記事へのリンクや楽しめるコンテンツをサイト内に配することは、回遊性を高めて滞在時間を延ばすのに大きな効果を発揮した。しかし今ではメディアによってはSNS流入がほぼすべて、特にニュースやちょっとした記事に関してはその傾向が顕著だろう。

したがって独自コンテンツでサイト内をぐるぐる回らせるより、使いやすく見やすく共有しやすいデザインの方が結果として双方向メディアはうまくいくように思われる。それを体現しているのがmediumだと僕は考えている。

なので社内wikiとしてのconfluenceがPC時代のデザインを踏襲するのは根本的に間違っている。それは単に頭に思いついたデザインの骨格をかっこよくしていこうとするだけの作業で、良いデザインにはいっこうに近づけない。

情報を共有し、見て、みんながなにかをやっていることを感じながらたまに覗ければよいのだ。

 

このブログもいいかげんに移行したい…

AITalk WebAPIを使ってwavを生成してs3に保存するaws lambda

LINE BOT AWARDSのハッカソンに参加した。ぷ◯きゅあがタスクの終了や寝る時間などを通知すると同時に音声合成でしゃべってくれる、という(いちおう)親子向けのBOTを作った。

LINE apiはeventに応じてwebhookが飛んでくる仕様になっているため、serverlessのアーキテクチャでシステムを作った。つまりlambda、step functionsをはじめとしたaws漬けだったのだが簡単に優れた設計のアプリが作れて僕スゴいじゃなくてawsマジすごい。

そのソースコードも公開する予定なのだが、スポンサー企業でもあったAITalkさんのAPIを呼んで音声合成したWAVEファイルをs3に保存するところは汎用性が高そうなのでgithubにrepositoryを作った。

https://github.com/Drunkar/aitalk_webapi_wav_generator_lambda

中身もいちおうここに貼っておく。めんどくさかったのは、jsのaws-sdkにはs3にファイルをアップロードする方法がなかった(rubyにはあるみたい)ので、jsのオブジェクトとしてメモリに保持した状態でputObject()することでI got Kotonaki. たぶんstreamを理解している人ならば一時ファイルとして/tmp以下に保存することなくs3にアップロードするコードが書けると思う。


var http = require("http");
var fs = require("fs");
var aws = require("aws-sdk");

var api_url = "http://webapi.aitalk.jp/webapi/v2/ttsget.php";

exports.handler = function(event, context) {
    var request_url = api_url +
        "?username=" + encodeURI(event.aitalk_username) +
        "&password=" + encodeURI(event.aitalk_password) +
        "&text=" + encodeURI(event.text) +
        "&speaker_name=" + encodeURI(event.aitalk_speaker_name) +
        "&volume=" + encodeURI(event.aitalk_volume) +
        "&speed=" + encodeURI(event.aitalk_speed) +
        "&pitch=" + encodeURI(event.aitalk_pitch) +
        "&range=" + encodeURI(event.aitalk_range) +
        "&ext=wav&use_wdic=1";

    var outFile = fs.createWriteStream("/tmp/" + event.filename);
    // start download
    http.get(request_url, function(res) {

        // output as a file
        res.pipe(outFile);

        // download end
        res.on("end", function() {
            outFile.close();

            // open the wav file as a js object and putObject to S3
            var s3 = new aws.S3();
            fs.readFile("/tmp/" + event.filename, function(err, data) {
                if (err) {
                    return console.log(err);
                }
                var params = {
                    Bucket: event.bucket,
                    Key: event.filename,
                    Body: data,
                    ContentType: "audio/wav",
                    ACL: "public-read"
                };
                s3.putObject(params, function(err, data) {
                    console.log(err, data);
                });
            });

        });
    }).on("error", function(e) {
        context.done("error", e);
    });
};

テストイベントを以下のように飛ばせばおk。


{
  "aitalk_username": "",
  "aitalk_password": "",
  "aitalk_speaker_name": "nozomi_emo",
  "aitalk_volume": "2.00",
  "aitalk_speed": "1.20",
  "aitalk_pitch": "0.90",
  "aitalk_range": "2.00",
  "text": "戦争に負けたから堕ちるのではないのだ。人間だから堕ちるのであり、生きているから堕ちるだけだ。",
  "filename": "voice.wav",
  "bucket": ""
}

NeoPixel系のRGB LEDがたくさんあるので調べてみた

NeoPixelってなんですか

Adafruitが販売している、シリアル通信でRGB値が制御できるLEDのこと。ここではトップ画像にあるような、マイコンを内蔵したRGB LEDチップについて述べる。厳密にはNeoPixelとはこれらマイコン付RGB LEDを総称したadafruitの商品シリーズ名である。

NeoPixelの歴史

小型のマイコン内蔵RGB LEDが出てきてからの歴史は以下の感じ。

  1. WS2812時代: 元祖NeoPixel? 6つのピンのうち5つを使用し、LED用のpowerとcircuit用のpowerが分かれていた。
  2. WS2812B時代: powerが1つに統合されて4ピンに。
  3. SKの登場: WS2812BのクローンであるSK6812が登場。製造元が違うと思われるがどちらもNeoPixelとして公式に販売されており同じ明るさ、色、プロトコルで動作する。
  4. DotStarの登場: 新たな商品ラインナップとして高リフレッシュレートのDotStarシリーズが登場。チップ型番が”APA”からはじまる。

販売店や製造元

選び方

POV[Persistent Of Vision] に使うのならばDotStar、それ以外ならNeoPixelで一番手に入りやすいWS2812B、SK6812が良い。adafruitの公式ショップで買うとめちゃくちゃに高いが、Aliexpress等で半額以下で手に入る。秋月とかLEDピカリ館でも売っている。

参考: NeoPixel vs DotStar

https://learn.adafruit.com/adafruit-dotstar-leds/overview#dotstars-vs-neopixels

NeoPixelsの方が安いし扱いやすくform-factorも多様なので、POV(persistence-of-vision)のように高リフレッシュが必要とか、割り込みが必要な処理の中で使ってるとかでない限りNeoPixelで良いっぽい。

参考: 各製品の特徴

1. WS2812(元祖NeoPixel?)

6つのピンのうち5つを使用し、LED用のpowerとcircuit用のpowerが分かれていた。
コレ以前の世代(WS2802)は5mm×5mmより大きいledしかなかったもよう。

2. WS281X, SK681X系(WS2812BやSK6812等、最もよく知られたNeoPixel)

WS2812からpowerが1つに統合されて4ピンになった。
XT1511というクローンもあるようだがその詳細はよくわからん。
WS281X系はマイナーアップデート版( http://www.instructables.com/id/Compare-SK6822-WS2813-APA102-SK9822/step2/WS2813-and-SK6822-LED/ )らしいがあまり手にはいらないので、大量に使いたい場合はWS2812BかSK6812に限る。

重さ

http://www.akiba-led.jp/product/1499
この防水stripを5LED分切り出してみると、1.07g。防水ビニルを剥がすと0.43g。

SK6812MINI

通常のNeoPixelは5mm×5mmだが、こちらは3.5mm×3.5mm。サイズがシビアな場合に。

https://cdn-shop.adafruit.com/product-files/2686/SK6812MINI_REV.01-1-2.pdf

ちなみに香港国際空港には全面LEDサイネージとなっている柱がある。液晶と比べてフチがないのですごく目を惹くが、このディスプレイに使われてるLEDは2mm-3mm角だった。どこで手に入るのだろう。

3. WS2822, SK6822 (進化版だが流通量が少ない)

各LEDにIDを振ることで1つのLEDが壊れてもstripの後ろが消えることがなくなった。しかしIDを送ったりするためピンは6本に戻った。WS2822は特にあまり出回っていない。

シリアルLED(WS2822S)をつかってみました。

git stashでオートセーブを実現するatom packageを作った

(この記事はAtom Advent Calendar 2016 に参加しています: http://qiita.com/advent-calendar/2016/atom )

 

かつて、こんなことはなかったでしょうか:

チームでgitを使っていて、masterの変更を反映させたいとき。

「ローカルの編集を退避させたいのだけど、stashでなんかよくわからん記録をつくるほどでもないし、コンフリクトしているファイルだけcheckoutしちゃおう。」

「よし、mergeできた。(俺もgit使いこなせるようになってきたナァ)」

―10分後

「よし、全体をbuildしてruntimeテストしよう」 → ERROR

ナンデ!?

 

gitの操作によって必要なローカルの変更を削除しちゃう経験、ありませんでしたか?僕はありました。

むしゃくしゃしたのでこれを解消するatom packageを作りました。(実際にはどちらかというと泣きそうになりました)

git-auto-stash

https://atom.io/packages/git-auto-stash です。

これを導入することで、定期的にgit stashが作られ、ファイル喪失の悲劇が多少減るのでは、と思っています。ぜひ使っていただいて、必要な機能などフィードバックをください。

 

自動保存を実現するしくみ

gitってファイルの履歴が保存されるんだし、gitの機能をどうにか使ってこの自動保存の仕組みを作れないか、と考えていたところ、「working treeに影響を及ぼさずにgit stashを作る方法」があることを知りました。

git stash create + git stash store -m <コメント> <hash>

です。

これを定期的に行うことで、トラッキングされているファイルであれば、stashに保存されるようになります。こちらはなにも考えなくてよしなにしてくれるというのが素晴らしいですね。具体的には、atom.workspace.observeTextEditorsで取得できるeditorのonDidStopChangingを使って保存のトリガーとしています。

何分ごとに保存するか、auto stashの最大数はいくらにするかはsettings画面から指定できます。

 

atomナンデか

DropboxやTimeMachineでいいじゃん、という人もいるでしょう。

しかしこうした汎用的なサービスはいちいち過去ファイルを掘っていくのが面倒だし、それならば開発の際に必ずと言っていいほどお世話になるgitとatomで完結するほうが、僕には気持ちの良い解決に思えたのです。

また、sublimetextじゃないの?て人もいるかと思いますが、もうatomに乗り換えちゃいなよ、と言っておきます。それぐらいatomは進化しています。

atomはsublimetextよりも思想的に優れて(electronを採用してる点とか)いたものの恋に落ちるような心地よさは微塵も無く、僕も何度か乗り換えを試みましたが最終的には殺意とともに離別したものでした。ところが今年の10月ごろに半年ぶり4度目ぐらいの乗り換えを試みたところ起動はすんなり、packageもほぼエラーが起きない、書いていてウザい機能がオプションで無効化できる、さらにelectronならではの異常に便利なpackage群が僕を待っていました。

ES6ムズいね

はじめてES6を触ったのでPromiseの理解に最初はとても苦しみました。結果なんとか動くコードにはなったものの間違いなくベストプラクティスに則っていないため、pull requestお待ちしております。

いまは指定した分数ごとにauto stashを行うだけですが、1分前、10分前、30分前、60分前、3時間、6時間、12時間、24時間ぐらいに一定間隔の過去stashを保存しておく機能は今後追加したいなと思っています。

XYZware ProのTutorial Panelを消す

Da Vinci ProをはじめXYZプリンティングの3DプリンタのクライアントソフトであるXYZware Proでは、起動のたびにチュートリアル画面がかなり大きなウインドウで上に出てきて死ぬほどうざい。

スクリーンショット 2016-09-03 11.58.41

下の方のモデルをクリックしてしまうとstlがロードされてしまうし、上のバナーをクリックするとサイトに飛ばされてしまう。マジでいらないのだけど消すオプションが無い。ユーザーをバカにしてるのかな?XYZ Printingのソフトウェアは全般的にクソゴミなのでこちらでなんとかするしかありません。

このバナー画像自体はホームディレクトリ直下の.XYZware/.ADsystem/あたりから取ってきてるらしい。

.ADSystemをリネームしてみたが、次回起動時には新たにディレクトリが作られてしまった。どうやらApplicationフォルダ内からコピーしてきてるっぽい。意味あんのかなコレ。

仕方ないので、.XYZware/.ADsystemのパーミッションを変更して、通常ユーザーでは読み取り不可にすることで問題が解決した。


sudo chown -R root ~/.XYZware/.ADsystem
sudo chmod -R 700  ~/.XYZware/.ADsystem

ls -la ~/.XYZware/ | grep .ADsystem
drwx------   3 root       284077650       102 Sep  3 11:49 .ADsystem

こうしてまた心の平和が保たれたのだった。

Da Vinci Proの設定まとめ

Da Vinci Proが結構追い込めて来たので設定を記録しておく。

https://github.com/Drunkar/slic3er-settings-for-da-vinci-pro

ポイントは、

  • スライサーにSlic3erを使う

こと。これをやらないと下記動画のように水平にずれてプリントされがちになる。

動画のとおりにカッターの刃をかませるだけでは解消しなかったが、Slic3erでg-codeを生成するようにしたら治った。

ヒゲを少なくするためにretractionを4.5mmにしている。

Curaも使ってみたがあまりヒゲは解消されなかった。

g-codeのハマりどころ

Da Vinci Proのg-codeでの温度設定はM140 (Bed (no wait))、M190 (Bed (wait))、M104 (Extruder (no wait))、M109 (Extruder (wait)) の4つがあるが、no waitのコマンドで温度設定後にwaitコマンドをそれぞれ発行しないと、設定温度に達していないのにプリント開始したり別の温度で開始したりととっても面倒なことになる。

下記のようになっていればOK (例: エクストルーダ 230℃、ベッド90℃)


M140 S90 ; Bed (no wait)
M190 S90 ; Bed (wait)
M104 S230 ; Extruder (no wait)
M109 S230 ; Extruder (wait)

post-scriptでやっていること

Slic3erで出力されるg-codeでは、温度上昇完了後にfirst layer heightで最初の造形地点へと移動する。Da Vinci Proだとだいたいエクストルーダがベッドの端にぶつかってそのうち壊れそうなので、post processing scriptで移動前にz方向にエクストルーダを上昇させるようにg-codeを編集している。

OpenSCADのテスト with CircleCI

(2016-09-06 追記) ——————————————-

How To Install OpenSCAD 2015.03 On Ubuntu 14.10, Ubuntu 14.04, Ubuntu 12.04 And Derivative Systems

この記事にあるように、PPAを使ったら最新版がもっと簡単にいれれるのでこっちがおすすめ。

——————————————————————

OpenSCADのテストってどうすれば良いのだろうか

  • とりあえずモジュールがビルドできる
  • 変数の未定義はなぜかERRORでなくWARNINGとして処理されるので、WARNINGでもビルド失敗としたい

完成品は https://github.com/Drunkar/openscad_modules です。CircleCIによってstlが生成されます。

1. circle.yml: OpenSCADのバージョンに注意

OpenSCADはコマンドラインでビルド可能なのでとりあえずcircleciでビルドしてみると、謎のsyntax errorが発生する。。。

なんかよくよく調べてみると昔のOpenSCADでは多重use/includeをすると全く関係のない行でsyntax errorが発生するというバグがあった模様

そんでUbuntu 14.04 trustyのapt-getでインストールされるOpenSCADは2013.01+dfsg-2.2でこのバグに引っかかってるらしい

http://packages.ubuntu.com/ja/trusty/openscad

なのでただのapt-getじゃなくて新しいパッケージを取ってこないといけない。

https://launchpad.net/~openscad/+archive/ubuntu/releases/+build/7368891

trustyでもOpenSCAD 2015.03-1+dfsg-0.1いけるやん!てことでcircle.ymlはこんな感じになります


general:
    branches:
        ignore:
            - images

machine:
    timezone: Asia/Tokyo
    python:
        version: 3.5.1

dependencies:
    pre:
        - sudo apt-get update
        - sudo apt-get install libboost-filesystem1.54.0 libboost-program-options1.54.0  libboost-regex1.54.0 libglew1.10 libopencsg1 libqt5scintilla2-11 libcgal10
        - wget https://launchpad.net/~openscad/+archive/ubuntu/releases/+build/7368891/+files/openscad_2015.03-1+dfsg-0.1~trusty1_amd64.deb && sudo dpkg -i openscad_2015.03-1+dfsg-0.1~trusty1_amd64.deb
        - sudo apt-get update
        - sudo apt-get install openscad
        - sudo pip install --upgrade pip
        - sudo pip install -r requirements-dev.txt

test:
    post:
        - invoke test

 

おわかりいただけたでしょうか。testはinvokeで行います。なぜならローカルでも実行できるからです。

ではお次はtestの中身です

2. test: “WARNING”を検出してエラーにする

なんでかしらんけど、OpenSCADは未定義の変数があるとその変数に1を代入してWARNINGを出して実行を続けます。

どうみてもエラーだと思いますけどそうなっているので仕方ない。

invokeでnosetestsを呼び出します。(tasks.py)


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

@invoke.task
def test(ctx):
    invoke.run("nosetests -v -s")

 

すると test_build_all.py がテストスクリプトと判断され実行されます。

ここではPythonのsubprocess.Popenでopenscadコマンドを実行し、stdoutとstderrに”WARNING”または”ERROR”のどちらかの文字が含まれていればエラーを発生させています。CircleCIで生成したファイルは、CIRCLE_ARTIFACTSという環境変数に記載されたディレクトリに保存することでダッシュボードからダウンロード可能になるので、openscadの-oオプションで書き出すパスを指定しています。



#!/usr/bin/env python
# coding: utf-8
import os
from glob import glob
import subprocess

CMD = "openscad -o "
OUTPUT_PATH = os.environ["CIRCLE_ARTIFACTS"]


def test_build_all():
    for file in glob("modules/*.scad"):
        print("--------------------------------------------------------------")
        print(file)
        output_file = os.path.splitext(os.path.basename(file))[0]
        p = subprocess.Popen(["openscad", "-o", OUTPUT_PATH + "/" + output_file + ".stl", file],
                             stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        out, err = p.communicate()
        error_count = out.count(b"ERROR") + err.count(b"ERROR")
        warning_count = err.count(b"WARNING") + out.count(b"WARNING")
        expect = 0
        print("stdout: " + out.decode("utf-8"))
        print("stderr: " + err.decode("utf-8"))
        try:
            assert error_count + warning_count == expect
        except AssertionError:
            raise Exception("ERROR or WARNING exists!")

これでモジュールづくりが捗ります

まだTOCの無いMarkdownで消耗してるの?

TOC Plugin for Sublime Text( https://github.com/naokazuterada/MarkdownTOC )が素晴らしすぎるのでみなさまnoteで稼ぐ前に入れましょう。

Package InstallerでMarkdownTOCをシュゥゥゥーッ!!!

おもむろに Preferences > Package Settings > MarkdownTOC > Settings – User を開き


{
  "default_autolink": true,
  "default_bracket": "round",
  "default_depth": 3,
  "default_indent": "\t"
}

 

と入力します。

あとは

ボールを

スクリーンショット 2016-08-03 21.37.22

相手のスクリーンショット 2016-08-03 21.38.39

ゴールに
スクリーンショット 2016-08-03 21.38.46

シュゥゥゥーッ!!スクリーンショット 2016-08-03 21.39.50

超!エキサイティン!! 

Pythonのロギング

pythonの公式ドキュメントはどうにも不自由な日本語なのでまとめ直し

Loggingモジュールのイメージ

Loggerオブジェクト

loggerオブジェクトを各モジュールに明示する( logging.getLogger(“hogehoge”) )ことで、ログを収集する。

loggerは名前で管理され、違うモジュールでも同じ名前を指定すると同じloggerになる。

木構造

loggerは階層構造を持ち、名前をピリオドで分割することで表現する。

Python パッケージ名前空間におけるモジュール名は __name__ で取得できるので、


logging.getLogger(__name__)

を使ってloggerをモジュール単位で構成することが推奨される。

loggerとhandlerを組み合わせて君だけの最強のloggingを手に入れろ!

loggerがログを収集するものだとすれば、handlerはログを吐き出すオブジェクトである。

loggerとhandlerは多対多で紐付けることが可能である。

標準出力用のhandlerとログファイル出力用のhandlerを用意してどちらもルートロガーに紐付ければ、そのアプリケーションの全loggerの出力を標準出力&ログファイルに出力できる。

 logging

複数モジュールでstdoutとファイルにログを吐き出すサンプル

  • 構成例

# 実行ファイル
cook_sukiyaki.py
  
# 設定ファイル
settings.py
  
# モジュール群
Models
  |- Nabe.py
  |- Cooker.py
  |- SukiyakiGuzai.py
  |- Soup.py
  
# サブモジュール群
AussieBeef.py        # SukiyakiGuzai.pyでimport
Gas.py                     # Cooker.pyでimport
   :
   :
  • settings.py

#!/usr/bin/env python
# coding: utf-8
import os
import argparse
import logging
import logging.handlers
  
  
# デバッグか否かをコマンドラインオプションで指定
parser = argparse.ArgumentParser(description="Sukiyaki tsukuruyo!")
parser.add_argument("-d", "--debug", action="store_true", help="Debug mode.")
parser.add_argument("-b", "--beef", type=str, default="aussie", choices=["aussie", "koube"], help="Beef choice.")
# 引数のparse
args = parser.parse_args()
 
 
if args.debug:
    LOG_LEVEL = logging.DEBUG
else:
    LOG_LEVEL = logging.INFO
logger = logging.getLogger("") # root loggerに対して設定することで、これ以後使うloggerすべてに共通の設定が適用される。
formatter = logging.Formatter(
    fmt="%(asctime)s:[%(name)s] %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
logger.setLevel(LOG_LEVEL)
 
# stdout出力
stream_handler = logging.StreamHandler()
stream_handler.setFormatter(formatter)
stream_handler.setLevel(LOG_LEVEL)
logger.addHandler(stream_handler)
 
# ログ出力
file_handler = logging.handlers.RotatingFileHandler(
    os.path.join(os.path.abspath(os.path.dirname(__file__)), "log", "app.log"),
    maxBytes=50000000, backupCount=5)
file_handler.setFormatter(formatter)
file_handler.setLevel(LOG_LEVEL)
logger.addHandler(file_handler)
  
BEEF = args.beef
  • cook_sukiyaki.py

#!/usr/bin/env python
# coding: utf-8
import settings
  
from Nabe import Nabe
from Cooker import Cooker
from SukiyakiGuzai import SukiyakiGuzai
from Soup import Soup
  
from logging import getLogger
# __name__でloggerを指定することで、pythonの階層構造と同じようにloggerの名前が付与される。
logger = getLogger(__name__)
  
def cook_sukiyaki(nabe, cooker, guzai, soup):
   logger.info("Sukiyaki tsukuruyo!")
   logger.debug("Beef: " + guzai.beef)
     :
     :
  
if __name__ == "__main__":
    nabe = Nabe()
    cooker = Cooker()
    guzai = SukiyakiGuzai(beef=settings.BEEF)
    soup = Soup()
  • モジュール、サブモジュールでのloggingでの呼び出し(例: Nabe.py)

#!/usr/bin/env python
# coding: utf-8
  
# これを書くだけでモジュールごとにloggerが作られる。
from logging import getLogger
logger = getLogger(__name__) 
  
class Nabe:
    pass
  • log例

2016-07-04 18:26:51:[cook_sukiyaki.py] Sukiyaki tsukuruyo!
2016-07-04 18:26:56:[cook_sukiyaki.py] Beef: aussie
2016-07-04 18:27:00:[Models.Nabe] Nabe oitayo!

ハマりがちな落とし穴

なんか実行してもstdoutに表示されないんだけど

参考