No Such Blog or Diary

«Prev || 1 | 2 | 3 |...| 57 | 58 | 59 || Next»

uWSGI + Flask + APScheduler の BackgroundScheduler でハマった

簡単な処理の自動化をして,それを APScheduler の BackgroundScheduler で指定時刻にやれるようにして,そのトリガを入れる WebUI を Flask で組んで,少し真面目に動かそうかと思って uWSGI で動かしたらスケジューラが動かんかった…… 残念.flask コマンドで動かすときには動作してるので,uWSGI での起動でなにか変なことが起きてるっぽい.

ということで,uWSGI がアプリを起動する辺りの情報を色々と調べた結果,たぶんワーカに app のコピーを設置する(fork する)ときに BackgroundScheduler のスレッドがどっか行っちゃってるんじゃないかな…… ということに思い至った.なので,--lazy-apps を付けて各ワーカ上で app をロードするようにしてみたら問題解決した.めでたし.

今日の結論:なにかおかしかったらまずは --lazy-apps 付けて試せ.

なお,そもそも複数ワーカで動くようなアプリだったらちゃんとしたスケジューラを使えということになるのでここらは関係ない気がする.自分が使うだけなのでワーカ数 1 で動かしつつ BackgroundScheduler のまま手抜きしてたらハマったという.ワーカ数 1 で動かしてたので(fork とかせずに)最初にロードされたのがそのままワーカで使われるかなと思ってたけどそんなことはなかった……

GPX をぶった切る

XML の文字列に変換した後に力技でぶった切ることにした.カシミール3Dの出したやつを gpxpy で処理した後のものならこれで切れるだろう.

cat > gpx_split5MB.py <<'EOS'
import gpxpy
import sys
import os
if len(sys.argv) < 2:
    print('python3 {0} gpx_file'.format(sys.argv[0]))
    sys.exit(0)
fname=sys.argv[1]
body,ext = os.path.splitext(fname)
def write(ts, head, last, i):
    with open(body + '.' + str(i) + ext, 'w') as of:
        of.write(head)
        for t in ts:
            of.write('\n')
            of.write(t)
        of.write('\n')
        of.write(last)
with open(fname) as f:
    g = gpxpy.parse(f)
    xml=g.to_xml(prettyprint=False)
    trks=xml.split('')
    head=trks[0]
    trks[-1],last=trks[-1].rsplit('\n',maxsplit=1)
    trks=trks[1:]
    i = 0
    k = 0
    s = 0
    ts = []
    while k < len(trks):
        if s + len(head) + len(last) >= 4800000:
             write(ts,head,last,i)
             s = 0
             i += 1
             ts = []
        s += len(trks[k])
        ts += [trks[k]]
        k += 1
    write(ts,head,last,i)
EOS

もうちょい美しいコードを書きたいところだけど動きゃいいや.

とりあえずこれで九州内の GPS 軌跡を google maps に乗せきれた.めでたし.

GPX を領域指定で切り出す

GPX ファイルの各点についておよそ九州を囲むポリゴン内に点があるかどうか判定して,九州内だけの GPS 記録を抜き出すスクリプトを書いてみた.めんどいのでポリゴン内の判定は shapely を使った.

cat > gpx_kyushu.py <<'EOS'
import gpxpy
import sys
import os
from shapely.geometry import Point
from shapely.geometry.polygon import Polygon
rs=[(129.2376598,33.3523184,0), (129.2820851,31.9550298,0), (130.3562645,30.897614,0), (131.6526512,30.968292,0), (132.2005334,32.8147117,0), (131.8853649,33.6580592,0), (130.5889782,34.1288502,0), (129.2376598,33.3523184,0)]
poly = Polygon(rs)
if len(sys.argv) < 2:
    print('python3 {0} gpx_file'.format(sys.argv[0]))
    sys.exit(0)
fname=sys.argv[1]
with open(fname) as f:
    g = gpxpy.parse(f)
    for t in g.tracks:
        for s in t.segments:
            s.points = [ p for p in s.points if poly.contains(Point(p.longitude,p.latitude)) ]
        t.segments = [ s for s in t.segments if len(s.points) > 0 ]
    g.tracks = [ t for t in g.tracks if len(t.segments) > 0 ]
    g.simplify()
    body,ext = os.path.splitext(fname)
    with open(body + '.kyushu' + ext, 'w') as of:
        of.write(g.to_xml(prettyprint=False))
EOS

だがしかし,これでも 5MB 越える年があるな…… でも10年分とかでもトータルでは 30MB になってないので,全体をこれで処理した後に 5MB 程度で分割するスクリプト通すのがよいかな.

make の再帰

hogeXXX というサブディレクトリ内に入って make するための親ディレクトリ用 Makefile が欲しくてググったら Run make in each subdirectory が引っかかった.困ったときの Stack Overflow.

ということで,書いた Makefile:

SUBDIRS := $(subst /.,,$(wildcard hoge*/.))
 
all: $(SUBDIRS)
 
$(SUBDIRS): FORCE
	$(MAKE) -C $@
 
FORCE:

これで親ディレクトリで make とやればサブディレクトリで make を実行してもらえる.めでたし.

Java の総称型の配列

要素の型Eを抽象化したデータ構造を Java で実装しようと思って E [] elements をフィールドに置きつつコンストラクタで elements = new E[8]; とかやったらコンパイラに怒られた.そういえば Generics のパラメータ E に対しての配列は作れなかったな……

ということで,elements = (E[]) new Object[8]; とかやって誤魔化す.JDK の ArrayList とかもこうやってるし,これが正しいのだろう.なにか色々なものを投げ捨てている気もするし警告でちゃうのだけど.

基本的には ArrayList 使っとけってことだろうけど,どうせなら配列生成の構文だけでも警告の出ない構文を用意してほしかった気がする.

Python は遅いのか?(その2)

昨日の続きで,ループ系の計算でも比較してみた.

#include
#include
int main(int argc, char *argv[])
{
	int sum = 0;
	int n = 0, i, j;
	n = atoi(argv[1]);
	for(j = 0; j  < 1000; j++) for(i = 0; i < n; i++) sum += i;
	printf("%d\n", sum);
	return 0;
}
import sys
n=int(sys.argv[1])
s=0
for j in range(0,1000): 
	for i in range(0, n):
		s += i
print(s)

結果:

hogehoge:~/work/pypytest$ gcc -O3 -o sumI sumI.c
hogehoge:~/work/pypytest$ time ./sumI 1000000
882236160
 
real    0m0.255s
user    0m0.252s
sys    0m0.000s
hogehoge:~/work/pypytest$ time pypy sumI.py 1000000
499999500000000
 
real    0m2.105s
user    0m2.088s
sys    0m0.020s

もう一回:

hogehoge:~/work/pypytest$ time ./sumI 1000000
882236160
 
real    0m0.155s
user    0m0.152s
sys    0m0.000s
hogehoge:~/work/pypytest$ time pypy sumI.py 1000000
499999500000000
 
real    0m2.130s
user    0m2.120s
sys    0m0.008s

10数倍くらい? 再起しまくりのフィボナッチと同じ程度.多倍長整数の演算になっている点が響いてるかも?

ということで,double でやった時:

hogehoge:~/work/pypytest$ time ./sum 1000000
5e+14
 
real    0m1.159s
user    0m1.156s
sys    0m0.000s
hogehoge:~/work/pypytest$ time pypy sum.py 1000000
4.999995e+14
 
real    0m3.085s
user    0m3.064s
sys    0m0.024s

こっちは 2~3倍程度.

ということで,Python は C の 3~10倍程度の遅さでしょう.なお,CPU は Intel(R) Xeon(R) CPU E5-2630 v3 @ 2.40GHz で.

«Prev || 1 | 2 | 3 |...| 57 | 58 | 59 || Next»
Search
Feeds

Page Top