dak ブログ

python、rubyなどのプログラミング、MySQL、サーバーの設定などの備忘録。レゴの写真も。

python で文字列を split

2018-11-25 14:57:42 | python
python で文字列を split する方法のメモ。

まず、普通に文字列を split する場合。
>>> str = 'a:b:c'
>>> str.split(':')
['a', 'b', 'c']


空文字列を split すると、空文字列が返されます。
>>> str = ''
>>> str.split(':')
['']


ちなみに、rubyだと空文字列を split すると空の配列が返されるのですが、
これと同じ動作を期待していました。
irb(main):001:0> ''.split(':')
=> []


返却される要素が空文字列であれば返さない、でよければ、
以下のようにすればOKです。
>>> str = ''
>>> [x for x in str.split(':') if x != '']
[]


ただし、'a::c' を split すると、真ん中の要素が消えてしまいます。
>>> str = 'a::c'
>>> [x for x in str.split(':') if x != '']
['a', 'c']


他によい方法があるかわかりませんが、ifで空文字列を判定して、
空文字列の場合には、[] を返すようにすればOKです。
うーん、美しくない。
>>> str = ''
>>> if str == '':
...   []
... else:
...   str.split(':')
...
[]

>>> str = 'a::c'
>>> if str == '':
...   []
... else:
...   str.split(':')
...
['a', '', 'c']





python で GC を実行する方法

2018-11-18 13:24:27 | python
python で Garbage Collection を実行する方法のメモ。

特に何も考えずに実行するなら、以下のように gc.collect() を呼び出すだけでOK。
import gc
gc.collect()


1行1jsonのデータを10万行読み込むたびに GC を実行してみたところ、
gc.collect() は10秒程度で完了。

rsync の timeout エラーについて調査した結果のメモ

2018-11-17 20:16:29 | linux
現在運用中のシステムでは rsync で数十台のサーバのログを、
ログ集計サーバに転送するようにしていますが、
送信側でエラーになっていて、転送に失敗することが多いため、
rsync のソース(rsync-3.1.3)を調べてみました。

結果的には、/etc/rsyncd.conf に "listen backlog = 転送元サーバ台数" を
設定すればよさそう。
ちなみに、listen backlog はデフォルトでは 5 になっています。

■loadparm.c

 /* ==== global_vars ==== */
 {
 ...
 /* listen_backlog; */          5,
 ...
 },

以下、クライアントからの要求をどのように処理しているかを、ソースを追って見てみます。
■clientserver.c

int daemon_main(void)
{
        ...

        start_accept_loop(rsync_port, start_daemon);
        return -1;
}

start_accept_loop() で accept しているので、次に start_accept_loop() を見てみます。
■socket.c

void start_accept_loop(int port, int (*fn)(int, int))
{
        ...

        /* open an incoming socket */
        sp = open_socket_in(SOCK_STREAM, port, bind_address, default_af_hint);
        if (sp == NULL)
                exit_cleanup(RERR_SOCKETIO);

        /* ready to listen */
        FD_ZERO(&deffds);
        for (i = 0, maxfd = -1; sp[i] >= 0; i++) {
★1             if (listen(sp[i], lp_listen_backlog()) < 0) {

        ...

        while (1) {
                ...

                if (select(maxfd + 1, &fds, NULL, NULL, NULL) < 1)
                        continue;

                for (i = 0, fd = -1; sp[i] >= 0; i++) {
                        if (FD_ISSET(sp[i], &fds)) {
                                fd = accept(sp[i], (struct sockaddr *)&addr,
                                            &addrlen);
                                break;
                        }
                }

                ...

★2             if ((pid = fork()) == 0) {
                        int ret;
                        for (i = 0; sp[i] >= 0; i++)
                                close(sp[i]);
                        /* Re-open log file in child before possibly giving
                         * up privileges (see logfile_close() above). */
                        logfile_reopen();
★3                     ret = fn(fd, fd);
                        close_all();
                        _exit(ret);
                } else if (pid < 0) {
                        rsyserr(FERROR, errno,
                                "could not create child server process");
                        close(fd);
                        /* This might have happened because we're
                         * overloaded.  Sleep briefly before trying to
                         * accept again. */
                        sleep(2);
                } else {
                        /* Parent doesn't need this fd anymore. */
                        close(fd);
                }
        ...
}

★1 で listen() していて、キューの最大長は第2引数の lp_listen_backlog() が指定されます。。
これがデフォルトでは 5 になっています(loadparm.c)。

★2 accept 後に fork しています。
select() で全クライアントとの読み書き処理を行っていたら...と思っていましたが、
fork() していたので、ひと安心。

★3 fn は start_accept_daemon() の第2引数の start_daemon()。
転送処理は start_daemon() で行っているはず。(ここで調査終了)


pythonの辞書をforループで処理する方法

2018-11-11 12:15:15 | python
pythonの辞書をforループで処理する方法のメモ。

keys(): キーのみを取得
values(): 値のみを取得
items(): キー、値のペアを取得

h = {1: 'a', 2:'b', 3:'c'}
for k in h.keys():
  print("key: %s" % (k))

key: 1
key: 2
key: 3

for v in h.values():
  print("val: %s" % (v))

val: a
val: b
val: c

for k, v in h.items():
  print("key: %s / val: %s" % (k, v))

key: 1 / val: a
key: 2 / val: b
key: 3 / val: c