Log4j2 で日付ベースのログローテーション
Log4j2 で吐いたログに対して日付ベースでのログローテーションと時限削除をしたいとき、
logrorated 等のローテーション管理ソフトウェアに任せると、Log4j2 側がファイルを見失ってしまうので、ローテーションを Log4j2 側で実現してやる。
<Appenders> <RollingFile name="hoge" fileName="logs/hoge.log" filePattern="logs/hoge.%d{yyyy-MM-dd}.log"> <PatternLayout pattern="%m%n" /> <TimeBasedTriggeringPolicy /> <DefaultRolloverStrategy> <Delete basePath="logs" maxDepth="1"> <IfFileName glob="hoge*.log" /> <IfLastModified age="7d" /> </Delete> </DefaultRolloverStrategy> </RollingFile> </Appenders>
DefaultRolloverStrategy
の min, max は 日付ベースのローテーションに対して効かないので、
自分で Delete
タグを使って削除をする必要がある。
単純に日付ベースで古いファイルを分けたいだけなら、特に何も考えず TimeBasedTriggeringPolicy
すればよい。
参考
[LOG4J2-435] Feature request: auto-delete older log files - ASF JIRA
ModelFormを利用して生成されるHTMLフォーム内の要素のnameタグを変更する
Django で Model を利用して入力画面を作る際には ModelForm
クラスを利用しますが、
Model のフィールド名と、投げられるリクエストの名前規則が一致しないことがあります。
リクエストを投げる側の動作を変更したくない(できない)場合、以下のように、ModelForm
クラス内のadd_prefix()
をオーバライドすることで、フォーム内の要素の name 属性の値を変更することが出来ます。
FIELD_NAME_MAPPING = { # 'Modelクラスのフィールド名' : 'name属性の値' 'field1': 'html_field1', 'field2': 'html_field2' } class MyForm(forms.ModelForm): class Meta: model = MyModel fields = '__all__' def add_prefix(self, field_name): field_name = FIELD_NAME_MAPPING.get(field_name, field_name) # dict に存在しない場合はフィールド名を利用する return super(MyForm, self).add_prefix(field_name)
この add_prefix()
メソッドですが、元々の動作はメソッド名の通り、 name 属性に設定されるフィールド名全てに接頭辞を与えるというものです。
この使い方の場合は、ModelForm
のフィールドとして prefix = 'hoge'
のように与えてやれば良いみたいです。
name 属性に設定する値をまるごと返す設計になっているので、Model クラスのフィールド名に縛られず自由に書き換えることができます。
参考
https://docs.djangoproject.com/ja/1.11/_modules/django/forms/forms/docs.djangoproject.com
argparseでハイフン入りオプションを使う
前略、pythonのargparseは非常に便利です。
add_argument()
の第一引数 name に対して--foo
のような文字列を与えてやると、parse_args()
で得られるオブジェクトに対して.foo
でアクセスし値を取ってこれる、という便利な実装になっています。
具体的にはこういう感じになります。
if __name__ == '__main__': parser = argparse.ArgumentParser(description=u'サンプル') parser.add_argument("--foo") args = parser.parse_args() if args.foo': print 'これで取れる'
ただ、一つだけよくわからないことがあります。 これ、nameにハイフンが含まれた時どうすんの?
というわけで実験しました。
if __name__ == '__main__': parser = argparse.ArgumentParser(description=u'サンプル') parser.add_argument("--hoge-fuga") args = parser.parse_args() if args.hoge_fuga': print 'これで取れる'
上記のように、--hoge-fuga
というオプションは.hoge_fuga
としてアクセスが可能です。
ハイフンは自動でアンダースコアに置換されるようです。
XmlSlurper の出力時に tag0 名前空間が付かないようにする
XmlSlurper クラスを利用して XML ドキュメントを読み込んだあと、
いろいろ処理をしたあとに書き出してみたら <tag0:xxx>
という名前空間になってしまって困る場合の対処法。
import groovy.xml.StreamingMarkupBuilder import groovy.xml.XmlUtil def doc = new XmlSlurper(false, false).parse(new File('input.xml')) // 色々処理する def out = new FileWriter('output.xml') XmlUtil.serialize(new StreamingMarkupBuilder().bind { mkp.yield doc }, out)
コンストラクタ XmlSlurper()
の第 2 引数に false を指定すると、tag0 名前空間が与えられるのを阻止できる。
(ちなみに第 1 引数は XML 文章の検証を行うかどうかを設定できるもので、引数なしの場合は false になる)
paint/paintComponentが呼ばれてないぞ?と思ったら
オーバーライドするとき、super() の呼び忘れがないかを確認する。
public class TestJPanel extends JPanel { public TestJPanel() { setBackground(Color.cyan); } protected void paintComponent(Graphics g) { super.paintComponent(g); // 背景を描く g.drawLine(50, 50, 200, 200); // 線を描く g.drawLine(200, 50, 50, 200); // 線を描く g.drawRect(50, 50, 150, 150); // 四角を描く } } }
のように、paintComponent()に描画処理を書いてしまって、paint()メソッドをオーバーライドしないようにする。
JPanelクラスのpaint()メソッドは内部でpaintComponent()を呼んでいるので、自分で手を加えると正常に動作しなくなる場合がある。
ImportError: No module named PyQt4
brew install pyqt
をしたあとに
import PyQt4
をしたら
ImportError: No module named PyQt4
と怒られてしまったときのメモ。
export PYTHONPATH=/usr/local/lib/python2.7/site-packages:$PYTHONPATH
を.bashrcもしくは.bash_profileに追加すればOK。
$ python >>>import sys >>>sys.path
してみて、どばーっと出てきたパスの中に'/usr/local/lib/python2.7/site-packages'があればOK。ダメなら.bashrcがちゃんと読み込めているか見直してみる。
この状態なら正常にimport出来るはず。