ValueError: unsupported format character ‘Y’ (0x59) at index 51

MySQL+Pythonのエラー

ValueError: unsupported format character 'Y' (0x59) at index 51

このようなエラーが出るときの対応。


import MySQLdb
ymd="2017-05-19"

con=MySQLdb.connect(user="root",password="",host="localhost",db="test")
cur=con.cursor()
cur.execute("set names utf8")   # 文字化け対応
cur.execute("select * from test_table where date_format(ymd,'%%Y-%%m-%%d')=%s",(ymd,))
for row in cur.fetchall():
  print(row[0])

これだと上記エラーが発生します。

ここに解決策が載っていました。

ポイントはsql文の文字列をformat()するだけ


import MySQLdb
ymd="2017-05-19"

con=MySQLdb.connect(user="root",password="",host="localhost",db="test")
cur=con.cursor()
cur.execute("set names utf8")   # 文字化け対応
cur.execute("select * from test_table where date_format(ymd,'%%Y-%%m-%%d')=%s".format(),(ymd,))
for row in cur.fetchall():
  print(row[0])

lambdaのAPIにキーを付与する

AWSの仕様がすぐ変わるのでメモ。

こちらの記事を参考にAPIGatewayにAPIキーをつけようとしたのですが、2017.5.16現在、仕様が変わってしまっているようでそのままでは設定できませんでした。

記事の中頃「API Keyの追加」の部分ですが、API Stage AssociationはAPI Keyのページには存在しません。

以下の手順となります

  • 左メニューのUsagePlansというメニューをクリック
  • createでNameに何か適当な名前を入れる。
  • リクエスト数にリミットをつけないのならば、Enable throttlingとEnable Quotaはチェックを外す
  • Add API Stageでデプロイ済みのAPIとStageを選択しチェックマークをクリック。Nextをクリック
  • Add API Key to Usage Planをクリックし、作成済みのAPI Keyの名前を入力。チェックマークをクリックしDone

これでAPIキーが付加されます。

AWSのlambdaでJavaを使う

ちょっとハマったのでメモ。JavaはMavenでコンパイルします。

Test.java


package com.example;

import java.util.Iterator;
import java.util.Map;

import com.amazonaws.services.lambda.runtime.Context;

public class Test {
	
	//http://stackoverflow.com/questions/35545642/error-executing-hello-world-for-aws-lambda-in-java
    public String handler(Map input, Context context){
    	String ret="";
    	Iterator ite=input.keySet().iterator();
    	while(ite.hasNext()){
    		String key=ite.next();
    		String val=input.get(key).toString();
    		ret+="("+key+","+val+"),";
    	}
    	return ret;
    }
}

pom.xml



  4.0.0

  com.example
  test
  0.0.1-SNAPSHOT
  jar

  Test
  http://example.com

  
    UTF-8
  

  
    
      junit
      junit
      3.8.1
      test
    
    
    
	    com.amazonaws
	    aws-lambda-java-core
	    1.0.0
	
  
  
  
    
    
      
        org.apache.maven.plugins
        maven-shade-plugin
        2.3
        
          false
        
        
          
            package
            
              shade
            
          
        
      
    
  


コンパイル

mvn package

Lambdaへアップロード

  • zipファイルをアップロード
  • Configulationを設定
  • RuntimeJava 8
    Handlercom.example.Test::handler

     これで動きます。テストの際に与えるパラメタの値が表示されます

torchをeclipseでデバッグ

torchというディープラーニングのライブラリが有ります。Luaで書かれているようであまり馴染みがなかったのですが、論文を読んでいて、サンプルをどうしても動かしたくてデバッグできる環境の構築を行った時のメモです

環境

  • MacOS Seirra 10.12.4
  • eclipse 4.6.3

こちらにubuntuの場合の設定方法があるのですが、Macではちょっと違いました。

luaインストール

brew install lua

これだけです

torchインストール

公式の手順通りにやれば問題なく終了します。

git clone https://github.com/torch/distro.git ~/torch --recursive
cd ~/torch; bash install-deps;
./install.sh

eclipseプラグイン

下記URLからLuaプラグインをインストールします。1.4.1が最新でした
http://download.eclipse.org/ldt/releases/milestones/

eclipseの設定

これが一番ハマりました。

環境設定 > Lua > Interpreters で Addで追加します。

Interpreter typeLua JIT 2.0
Interpreter executable/Users/yourname/torch/install/bin/luajit
Interpreter name Lua JIT
interpreter arguments-lenv -e “io.stdout:setvbuf(‘no’); if os.getenv(‘DEBUG_MODE’) then require ‘debugger’ ; require ‘debugger.plugins.ffi’end”
Linked Execution Environmentlua-5.1

また、Import…で/Users/yourname/torch/install/bin/torch-activateをインポートし環境変数を追加します

実行

こちらのサンプルを動かしてみます。
EclipseでLuaプロジェクトを作成し、srcディレクトリ内にファイルを作成します。
ここでポイントは、ファイルのパスをコード中に記述する際にはプロジェクトのトップからの相対パスを書きます。

download.py


print '==> downloading dataset'

-- Here we download dataset files. 

-- Note: files were converted from their original LUSH format
-- to Torch's internal format.

-- The SVHN dataset contains 3 files:
--    + train: training data
--    + test:  test data

tar = 'http://torch7.s3-website-us-east-1.amazonaws.com/data/mnist.t7.tgz'

if not paths.dirp('mnist.t7') then
   os.execute('wget ' .. tar)
   os.execute('tar xvf ' .. paths.basename(tar))
end

train_file = 'src/mnist.t7/train_32x32.t7'
test_file = 'src/mnist.t7/test_32x32.t7'

----------------------------------------------------------------------
print '==> loading dataset'

-- We load the dataset from disk, it's straightforward

trainData = torch.load(train_file,'ascii')
testData = torch.load(test_file,'ascii')

print('Training Data:')
print(trainData)
print()

print('Test Data:')
print(testData)
print()

----------------------------------------------------------------------
print '==> visualizing data'

-- Visualization is quite easy, using itorch.image().
if itorch then
   print('training data:')
   itorch.image(trainData.data[{ {1,256} }])
   print('test data:')
   itorch.image(testData.data[{ {1,256} }])
end

右クリックのRunで実行できます

Tensorflowのエラー

Tensorflowをバージョンアップすると、昔動いていたスクリプトが動かなくなったりします

    cell = tf.nn.rnn_cell.BasicLSTMCell(size, forget_bias=0.0)
AttributeError: 'module' object has no attribute 'rnn_cell'

こんなエラーとか。

こちらを参照し修正します。

これを

tf.nn.rnn_cell.BasicLSTMCell

これに変更

tf.contrib.rnn.BasicLSTMCell

Maven起動時のエラー

Mavenの起動時にエラーが出たのでメモ

エラーメッセージ

$ mvn package
メイン・クラスorg.codehaus.plexus.classworlds.launcher.Launcherが見つからなかったかロードできませんでした

対応方法

こちらを参考に

$ unset M2_HOME
$ mvn package

omp4jによる並列化

Pythonで並列化させたプログラムを走らせていたのですがあまりの遅さにJavaへと変更した際、並列化をomp4jで簡単にできたのでメモ。

omp4j

OpenMPの説明は、Wikipediaをみてもらうことにして、ソースコード中にコメントを書いておいて、コンパイルをすれば並列化プログラムの出来上がるという便利なライブラリ。

ここからJarファイルをダウンロードします。

wget https://github.com/omp4j/omp4j/releases/download/v1.2/omp4j-1.2.jar

Javaプログラム

簡単なプログラムを作成します。スレッド5で10回計算しています。


import java.util.Random;


public class OmpTest {
        private void run() {
                try {
                        // omp parallel for threadNum(5)
                        for (int i = 0; i < 10; i++) {
                                new Task1(i).call();
                        }

                } finally {
                        System.out.println("ThreadTest:finish");

                }
        }

        static class Task1{
                private int number;
                Task1(int number){
                        this.number=number;

                }
                public Long call()  {
                        System.out.println("Task1.start:"+this.number);
                        long sleep=new Random().nextInt(10)*1000;
                        long sum = 0;
                        for (int i = 1; i <= 100 * 10000; i++) {
                                sum += i;
                        }
                        try{
                                Thread.sleep(sleep);
                        }catch(Exception e){}
                        System.out.println("Task1.end:"+this.number+",sleep="+sleep);
                        return sum;
                }
        }

        public static void main(String[] argv){
                new OmpTest().run();
        }
}

シングルスレッド

普通にコンパイルします。シングルスレッドで動作します。


$ javac OmpTest.java
$ java OmpTest
Task1.start:0
Task1.end:0,sleep=3000
Task1.start:1
Task1.end:1,sleep=2000
Task1.start:2
Task1.end:2,sleep=1000
Task1.start:3
Task1.end:3,sleep=0
Task1.start:4
Task1.end:4,sleep=5000
Task1.start:5
Task1.end:5,sleep=6000
Task1.start:6
Task1.end:6,sleep=9000
Task1.start:7
Task1.end:7,sleep=3000
Task1.start:8
Task1.end:8,sleep=8000
Task1.start:9
Task1.end:9,sleep=2000
ThreadTest:finish

シリアルに計算されているのがわかります。

マルチスレッド

並列化できるようにコンパイルします。


$ java -jar omp4j-1.2.jar OmpTest.java
$ java OmpTest
Task1.start:3
Task1.start:1
Task1.start:2
Task1.start:4
Task1.start:0
Task1.end:1,sleep=0
Task1.start:5
Task1.end:0,sleep=3000
Task1.start:6
Task1.end:2,sleep=3000
Task1.end:5,sleep=3000
Task1.start:7
Task1.start:8
Task1.end:3,sleep=4000
Task1.start:9
Task1.end:4,sleep=7000
Task1.end:9,sleep=3000
Task1.end:6,sleep=8000
Task1.end:8,sleep=8000
Task1.end:7,sleep=9000
ThreadTest:finish

並列に計算できているのがわかります。
実際にはコンパイル時にコードを変換してコンパイルしています。
ここにソースコードを貼り付けると変換後のソースが表示されます。上記サンプルだとエラーになってしまいましたが、簡単なコードならばそのコードが表示されます。

まとめ

簡単にJavaのコードが並列化できます。色々と制約はありますが(変数関連など)、簡単に並列プログラムが作成できるのはメリットでしょう。

SQLiteをPythonからインメモリで使う

SQLite、手軽で便利なデータベースですが激しく使っていると速度が気になる時もあります。

SQLiteはインメモリデータベースもサポートしているので、既存のSQLiteのデータベースからインメモリ化して読み取り専用にすると早くなります。

データベース準備

適当に大きなデータベースを用意します。


#!/bin/env python
# coding:utf-8

import sqlite3

con=sqlite3.connect("test.db")
con.cursor().execute("CREATE TABLE test( key integer, val integer , primary key(key))")
con.commit()


for key in range(1,10000000+1):
  con.cursor().execute("insert into test values(?,?)",(key,key+1,))
con.commit()

1000万レコードのデータベースを作成しました。


$ sqlite3 test.db 
SQLite version 3.7.6.3
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> select count(*) from test;
10000000

プログラム

こちらを参考にプログラムを作成します。


#!/bin/env python
# coding:utf-8

import sqlite3
from StringIO import StringIO
import time
import random

# in memory化
con=sqlite3.connect("test.db")
tempfile=StringIO()
for line in con.iterdump():
    tempfile.write("%s\n" % line)
tempfile.seek(0)
mcon=sqlite3.connect(":memory:")
mcon.cursor().executescript(tempfile.read())
mcon.commit()
mcon.row_factory=sqlite3.Row


current_milli_times = lambda: int(round(time.time() * 1000))

print "ready.."
# normal
# select 10000 times
N=10000
nstart=current_milli_times()
for i in range(N):
    key=random.randrange(10000000)
    res=con.cursor().execute("select * from test where key=?",(key,))

nend=current_milli_times()
print "normal:"+str(nend-nstart)


# inmemory
mstart=current_milli_times()
for i in range(N):
    key=random.randrange(10000000)
    res=mcon.cursor().execute("select * from test where key=?",(key,))
mend=current_milli_times()
print "inmemory:"+str(mend-mstart)

conのコネクションが通常のデータベースアクセス、mconがデータベースファイルをインメモリ化したものになります。10000回ランダムにSELECTしてみます。

結果

ready..
normal:414
inmemory:171

大学のスパコンで計算したのですが2倍以上の差が出ました。

Rをソースコードからインストール

スーパーユーザ権限のないサーバにソースコードからインストールしてみたのでそのメモ

大学のサーバなど勝手になんでもインストールできない環境ではローカルのユーザ環境に色々とインストールしないといけません。今回はRをインストールしてみました

Rの取得

cranからRのソースコードをダウンロードしコンパイルします

wget https://cran.r-project.org/src/base/R-3/R-3.3.2.tar.gz
tar zxvfp R-3.3.2.tar.gz
cd R-3.3.2
mkdir builddir
cd builddir
../configure --prefix=/work/$USER/local --with-cairo --with-jpeglib --with-readline --with-tcltk --with-blas --with-lapack --enable-R-profiling --enable-R-shlib --enable-memory-profiling 

エラーになります

checking if bzip2 version >= 1.0.6... no
checking whether bzip2 support suffices... configure: error: bzip2 library and headers are required

足りないライブラリを入れていきます

bzip2

wget http://www.bzip.org/1.0.6/bzip2-1.0.6.tar.gz
tar zxvfp bzip2-1.0.6.tar.gz
cd bzip2-1.0.6

このあたりを参考にMakefileを修正しておきます。CFLAGSに-fPICを追加します

CFLAGS=-fPIC -Wall -Winline -O2 -g $(BIGFILES)

makeします

make -f Makefile-libbz2_so
make clean
make
make -n install PREFIX=/work/$USER/local
make install PREFIX=/work/$USER/local

Rのconfigを再開します。この際、オプションにライブラリのパスを入れます

../configure --prefix=/work/$USER/local --with-cairo --with-jpeglib --with-readline --with-tcltk --with-blas --with-lapack --enable-R-profiling --enable-R-shlib --enable-memory-profiling CPPFLAGS="-I/work/$USER/local/include" LDFLAGS="-L/work/$USER/local/lib"

またエラーです

checking for lzma_version_number in -llzma... no
configure: error: "liblzma library and headers are required"

xz

xzライブラリを入れます。

wget http://tukaani.org/xz/xz-5.2.3.tar.gz
tar zxvfp xz-5.2.3.tar.gz 
cd xz-5.2.3
./configure --prefix=/work/$USER/local
make install

Rのconfigを再開

../configure --prefix=/work/$USER/local --with-cairo --with-jpeglib --with-readline --with-tcltk --with-blas --with-lapack --enable-R-profiling --enable-R-shlib --enable-memory-profiling CPPFLAGS="-I/work/$USER/local/include" LDFLAGS="-L/work/$USER/local/lib"

またエラー

checking for pcre_fullinfo in -lpcre... no
checking whether PCRE support suffices... configure: error: pcre >= 8.10 library

pcre

pcreライブラリを入れる。ここで、UTF8を有効にしておきます

wget https://ftp.pcre.org/pub/pcre/pcre-8.10.zip
unzip pcre-8.10.zip 
cd pcre-8.10
./configure --prefix=/work/$USER/local/ --enable-utf8
make install

Rのconfigを再開

checking if libcurl is version 7 and >= 7.28.0... no
configure: error: libcurl >= 7.28.0 library and headers are required with support for https

またエラーです

curl

wget --no-check-certificate https://curl.haxx.se/download/curl-7.47.1.tar.gz
tar zxvfp curl-7.47.1.tar.gz 
cd curl-7.47.1
./configure --prefix=/work/$USER/local
make -j3
make install

Rのconfigを再開

../configure --prefix=/work/$USER/local --with-cairo --with-jpeglib --with-readline --with-tcltk --with-blas --with-lapack --enable-R-profiling --enable-R-shlib --enable-memory-profiling CPPFLAGS="-I/work/$USER/local/include" LDFLAGS="-L/work/$USER/local/lib"

成功しました

コンパイル

make

またエラー。。

/work/xxxxx/work/R-3.3.2/builddir/bin/exec/R: /usr/lib64/libgomp.so.1: version `GOMP_4.0' not found (required by /work/xxxxx/work/R-3.3.2/builddir/lib/libR.so)

これは使っているGCCとそのライブラリがずれていたためでした。
LD_LIBRARY_PATHに使っているGCCのライブラリパスを前の方に追加し再度make

make
make install

これでOKです。

RASPBIAN JESSIEでSSH接続

ちょっとはまりました。

RASPBIAN JESSIEの2016-11-25バージョンではデフォルトでSSH接続が外部からできなくなってしまいました。

外部から接続しようとするとこんな感じ

$ ssh -vvv 192.168.11.102 -l pi
OpenSSH_7.2p2, LibreSSL 2.4.1
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: /etc/ssh/ssh_config line 20: Applying options for *
debug2: resolving "192.168.11.102" port 22
debug2: ssh_connect_direct: needpriv 0
debug1: Connecting to 192.168.11.102 [192.168.11.102] port 22.
debug1: connect to address 192.168.11.102 port 22: Connection refused
ssh: connect to host 192.168.11.102 port 22: Connection refused

どうやら仕様変更があったようです
http://downloads.raspberrypi.org/raspbian/release_notes.txt

2016-11-25:
  * SSH disabled by default; can be enabled by creating a file with name "ssh" in boot partition
  * Prompt for password change at boot when SSH enabled with default password unchanged
  * Adobe Flash Player included
  * Updates to hardware video acceleration in Chromium browser
  * Greeter now uses background image from last set in Appearance Settings rather than pi user
  * Updated version of Scratch
  * Rastrack option removed from raspi-config and Raspberry Pi Configuration
  * Ability to disable graphical boot splash screen added to raspi-config and Raspberry Pi Configuration
  * Appearance Settings dialog made tabbed to work better on small screens
  * Raspberry Pi Configuration now requires current password to change password
  * Various small bug fixes
  * Updated firmware and kernel

解決方法はブートパーテーションにsshという名のファイルを作るだけ。

$ cd /boot
$ sudo touch ssh
$ sudo reboot

セキュリティのためとはわかりますが、いきなり塞がれると困ってしまいました。