Tensorboardが表示されない

Jupyterノートブックで

%load_ext tensorboard
%tensorboard --logdir="/tmp/ranking_model_dir" --port 12345

のように書いて実行したら、

Reusing TensorBoard on port 12345 (pid 808444), started 1:12:35 ago. (Use '!kill 808444' to kill it.)

という感じで、Tensorboardが表示されず、プロセスをkillしようにもそのようなプロセスがいないような場合、前の情報が残っているだけかもしれません。ということで、

$ rm -rf /tmp/.tensorboard-info/

という感じで消してあげると表示されるようになりました。

FastAPIで画像をアップロードしてダウンロードする

FastAPIを使って、画像をアップロードして、OpenCVで変換とかして、返却するというのをやりたかったのだが、イマイチな部分もある気はするけど、メモがてらに残しておく。一応、アップロードされたファイルは一旦、一時ファイルに保存している(保存しなくても良いかもしれないけど…)。そんで、process(img)の中で、画像のimgのnumpy arrayを何か変換して、戻した画像のimg_convertedのnumpy arrayを作る。あとは、img_convertedはオンメモリでcv2.imencodeで、png形式にして、Responseで返せば、画像がダウンロードされる。画像はマルチパートでアップロードする感じだけど、FastAPIのhttp://localhost:8000/docs/で送り方を確認すればよいはず。

from fastapi import FastAPI, UploadFile, File, HTTPException, Response
import cv2
import shutil
from pathlib import Path
from tempfile import NamedTemporaryFile

app = FastAPI()


@app.post("/convert/")
def convert(file: UploadFile = File(...)):
    filepath = save_upload_file_tmp(file)
    try:
        img = cv2.imread(str(filepath))
        img_converted = process(img) # OpenCVの変換処理とか
        _, img_enc = cv2.imencode('.png', img_converted)
        return Response(content=img_enc.tostring(), media_type='image/png')
    except Exception as e:
        raise HTTPException(status_code=500, detail='Failed to convert an image.')
    finally:
        filepath.unlink()


def save_upload_file_tmp(upload_file: UploadFile) -> Path:
    try:
        suffix = Path(upload_file.filename).suffix
        with NamedTemporaryFile(delete=False, suffix=suffix) as tmp:
            shutil.copyfileobj(upload_file.file, tmp)
        tmp_path = Path(tmp.name)
    finally:
        upload_file.file.close()
    return tmp_path

FastAPIでアップロードされたファイルの保存はこれを参考にした。

Python 3.7のインストールに失敗するときに

Ubunut 18.04にpyenvで以下のような感じでPython 3.7のインストールに失敗するときには

$ pyenv install 3.7.3
 Downloading Python-3.7.3.tar.xz…
 -> https://www.python.org/ftp/python/3.7.3/Python-3.7.3.tar.xz
 Installing Python-3.7.3…
 BUILD FAILED (Ubuntu 18.04 using python-build 1.2.11-11-g7dd50144)
 Inspect or clean up the working tree at /tmp/python-build.20190516184525.2792
 Results logged to /tmp/python-build.20190516184525.2792.log
 Last 10 log lines:
   File "/tmp/tmp97wtapkd/pip-19.0.3-py2.py3-none-any.whl/pip/_internal/commands/init.py", line 6, in 
   File "/tmp/tmp97wtapkd/pip-19.0.3-py2.py3-none-any.whl/pip/_internal/commands/completion.py", line 6, in 
   File "/tmp/tmp97wtapkd/pip-19.0.3-py2.py3-none-any.whl/pip/_internal/cli/base_command.py", line 20, in 
   File "/tmp/tmp97wtapkd/pip-19.0.3-py2.py3-none-any.whl/pip/_internal/download.py", line 37, in 
   File "/tmp/tmp97wtapkd/pip-19.0.3-py2.py3-none-any.whl/pip/_internal/utils/glibc.py", line 3, in 
   File "/tmp/python-build.20190516184525.2792/Python-3.7.3/Lib/ctypes/init.py", line 7, in 
     from _ctypes import Union, Structure, Array
 ModuleNotFoundError: No module named '_ctypes'
 Makefile:1130: recipe for target 'install' failed
 make: *** [install] Error 1

以下のような感じで、libffi-devを入れておく。

$ sudo apt install libffi-dev

Easter Eggs in Python

役に立たなそうな隠しコマンド的なやつたち。

Hello World

>>> import __hello__
Hello world!

The Zen of Python

>>> import this
The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than right now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!

Antigravity

>>> import antigravity     

Braces is Not a chance…

>>> from __future__ import braces
File "<stdin>", line 1
SyntaxError: not a chance

Ansible Vaultを使ってみる

セキュアな情報を含んだ情報をgitとかに素の状態で置いておけないので、Ansible Vaultはファイルを暗号化してくれるらしい。別にAnsible自体を使わなくても、ansible-vaultコマンドとして利用できるようなので試してみる。

まず、インストールしてみる。とはいえ、Pythonがある前提。

$ pip install ansible-vault

これでansible-vaultコマンドが利用できるようになる。ということで、適当なファイルを作ってencryptしてみる。

$ echo secret > password.txt
$ ansible-vault encrypt password.txt
New Vault password:
Confirm New Vault password:
Encryption successful
$ cat password.txt
$ANSIBLE_VAULT;1.1;AES256
...

という感じで、password.txtの中身が変わっているのが確認できる。今度は復号化をしてみる。

$ ansible-vault decrypt password.txt 
Vault password:
Decryption successful
$ cat password.txt
secret

パスワードはencrypt時に入力したものを入れる。password.txtが元に戻ったことを確認できた。

ansibleに関係なく手軽に利用できるので便利かもしれない。