sakemoto-san

ITエンジニアがWebサービス全般について書いていきます。

PythonでExifをいじる

exifreadというライブラリが有名らいし.githubにもあるし,pipでも入る. EXIF付きのファイルをopenして,process関数に渡すと,EXIFに含まれるtag, keyをパースしてくれる.

これを利用して,flickrから落としてた写真のファイル名のプレフィックスに日時を入れてソートするためにコーディングした.

import exifread
import sys
import os

'''
Inserting taken-date-time at the beggining of base filename.
'''

def getTakenDateTime(filename):
    with open(filename) as f:
        tags = exifread.process_file(f)

        for tag in tags.keys():
            if  'DateTimeOriginal' in tag:
                #print 'key=%s, val=%s' % ( tag, tags[tag] )
                datetime='%s' % tags[tag]
                datetime=datetime.replace(':', '')
                datetime=datetime.replace(' ', '_')
                return datetime

if __name__ == '__main__':
    for i in sys.argv[1:]:
        basename = os.path.basename(i)
        dirname = os.path.dirname(i)
        datetime = getTakenDateTime(i)
        src = i
        dst = '%s/%s_%s' % (dirname, datetime, basename )
        print basename, dst
        os.rename(src, dst)

Documentating codes

Source codeの中にドキュメントを書く各種の方法.だいたい統一されている. 結局,javaならjavadocに沿って,pythonならpydocに沿って書けば あとはdoxygenが自動的に生成してくれる. ただし,C++とかpython/pydocはあまりいい記述方式がないので, 全部javadoc形式に合わせるのが得策だ ろう.

Sample

念のためサンプルを置いておく

#include <iostream>

/** /class Mother2
* /brief This is BRIEF!!!
*
* I have a good cup.
*/
class Mother {
public:
/** Constructor!
*
* This is constructor, you know. This function does 
* - get the age from args
* - set the age to local var.
* -# hoge
* -# foo
* -# bar
* - hoge
*/
Mother(int age_=0){
age = age_;
} 
int Age(){return age;}

/**
* @author Masahiko Kitamura
* @param a first parameter to be processed
* @param b sencond parameter to be processed
* @return return (a+b)
*/
int Plus(int a, int b){ return a+b;}
private:
int age; ///< This is your age!
protected:

};

int main(){
std::cout << "Hello, world! " << std::endl;
Mother m;
std::cout << "m.Age(): " << m.Age() << std::endl;
return 0;
}

その他

ドキュメント化は,このインライン方式と,あとはusageヘルプ(コマンドをオプション無し実行した時のヘルプ表示)の2通りで書いておいたほうが良いだろう.

ドキュメント以外にテストコードもinline化できるので,ソースコードにいろいろ含まれそう.

Reference

ryu/lagopus環境設定用ansible playbook

大量のマシンにlagopusとryuをぶち込む必要が出てきたので,ansibleの勉強を兼ねて,ryu, lagopusの環境設定を行うplaybookを書いてみた. このplaybookでインストールされるものは下記の通り.

  • ryu
  • lagopus v0.2
  • dpdk-1.8.0

以下,そのコード

- hosts: lagopus
  vars:
    homedir: /home/lagopus
    DPDK_ver: dpdk-1.8.0
    lagopus_ver: lagopus
  user: shd
  sudo: yes
  tasks:
  - name: install basic tools
    apt: name={{ item }} update_cache=yes
    with_items:
      - build-essential
      - git
      - unzip
      - python-pip
      - python-dev
  
  - name: install python modules
    pip: name={{ item }} state=latest
    with_items:
      - six
      - pbr

  - name: install ryu
    pip:  name=ryu state=latest
  
  - name: install pkgs for DPDK compile
    apt: name={{ item }}
    with_items:
      - make
      - coreutils
      - gcc
      - binutils

  - name: install kernel header
    shell: "apt-get install -y linux-headers-$(uname -r)"
  
  - name: download DPDK
    command: wget http://dpdk.org/browse/dpdk/snapshot/{{ DPDK_ver }}.zip
    args:
      chdir: "{{ homedir }}"
      creates: "{{ homedir }}/{{ DPDK_ver }}.zip"

  - name: unzip DPDK
    command: unzip {{ DPDK_ver }}.zip
    args:
      chdir: "{{ homedir }}"
      creates: "{{ homedir }}/{{ DPDK_ver }}"
  
  - name: compile DPDK
    shell: "make config T=${RTE_TARGET} && make"
    args:
      chdir: "{{ homedir }}/{{ DPDK_ver }}"
      creates: "/home/shd/dpdk-1.8.0/build/app/cmdline_test"
    environment:
      RTE_SDK: "{{ homedir }}/{{ DPDK_ver }}"
      RTE_TARGET: "x86_64-native-linuxapp-gcc"

  - name: clone lagopus src from github
    git:  repo=https://github.com/lagopus/lagopus.git
          dest={{ homedir }}/{{lagopus_ver}}
          version=HEAD

  - name: install pkgs for lagopus compile
    apt: name={{ item }}
    with_items:
      - libexpat-dev
      - libgmp-dev
      - libssl-dev
      - libpcap-dev
      - byacc
      - flex
      - python-dev
      - python-pastedeploy
      - python-paste
      - python-twisted


  - name: build and install lagopus
    shell: "./configure --with-dpdk-dir=${RTE_SDK} && make OPT_CFLAGS=\"-O3 -fomit-frame-pointer\" && make install"
    args:
      chdir: "{{ homedir }}/{{ lagopus_ver }}"
      creates: "/usr/local/sbin/lagopus"
    environment:
      RTE_SDK: "{{ homedir }}/{{ DPDK_ver }}"

  - name: rebooting!
    shell: reboot

でも,パフォーマンスの問題もあって,v0.1.1を使う場面もあるからそのバージョン切り替えもすんなり行くようなplaybookを作る必要がありそう.