20190622のPythonに関する記事は30件です。

Excelで1セル内に複数の書式(フォント)が混在するようなものをPythonで扱いたい

この記事の対象

タイトルにある「1セル内に複数の書式が混在するようなもの」とは、下図スクリーンショットのA2セルのようなものを想定しています。

キャプチャ.PNG

そして、本記事でやりたいことは、以下の2つです。(できるとは言っていない)

  1. 書式の違いを保持した状態でセルの値を読み取りたい(既存ファイルから)
  2. 1つのセルに対して複数の書式が混在した値を書き込みたい(新規ファイルへ)

というわけで、簡単に調べてみました。

結論

1.読み込み難しく、2.書き込みできそうといった感じでした。また、読み込みに関しては、将来的にはできるようになるかもという状態でした。

(もし、読み込みの方法をご存知の方がいらっしゃいましたらご指摘ただければ幸いです。)

複数書式の考え方

調べた感じ、おそらく、1つのセルの中の値は、プレーンテキストではなく、リッチテキストで格納されているものと思われます。よって、Excelのリッチテキストに対応したPythonライブラリがあれば、やりたいことが叶いそうです。

OpenPyXLの対応状況

xlsxファイルの読み書きをするライブラリで有名なの物の1つに、OpenPyXLがあります。しかし、2019/6/22現在、OpenPyXL(Version 2.6.2)はリッチテキストの読み書きには対応していなさそうです。(Issueに理由等が記されています。(英語))

しかし、需要はあるようで、BitBucket上で議論はされています(#224 Support of rich text in cells)。本プルリクエスト内のスレッドを読む感じですと、将来的には実装されるかもしれません。今後に期待。

このスレッド内でも言及されていますが、別ライブラリとして、XlsxWriterであれば、リッチテキストに対応しているみたいです。

XlsxWriterでリッチテキストを扱う(書き込み限定)

XlsxWriterは、名前を見てもわかる通り、書き込みオンリーです。既存のファイルを読み込んだりはできません。

公式で、リッチテキストを追加するサンプルがありました。

それにならって、冒頭のスクショのようなセルを作りたければ、下記のようなコードとなります。コメントも併せてご覧ください。

import xlsxwriter

## 準備
workbook = xlsxwriter.Workbook('TestFile2.xlsx') # 新規xlsxファイル作成
worksheet = workbook.add_worksheet()             # ワークシートの追加

## 書式の準備
red = workbook.add_format({'color': 'red'})                                     # 赤色
italic_underline = workbook.add_format({'italic': True, 'underline': True})     # 斜体と下線
bold = workbook.add_format({'bold': True})                                      # 太字
superscript = workbook.add_format({'font_script': 1})                           # 上付き文字(2にすると下付き文字)
superscript_purple = workbook.add_format({'font_script': 1, 'color': 'purple'}) # 紫色の上付き文字

## リッチテキストをA1セルに追加
worksheet.write_rich_string('A1', # セルを指定
                            'いろんな', # 基本的には、ひたすら引数に追加したい文字列を並べる
                            red, 'フォント', # 書式を設定したい場合は、書式オブジェクトを引数に加えると、直後の文字列のみその書式が適用される
                            '(', # 直前に書式オブジェクトが無い場合は、デフォルトの書式になる
                            italic_underline, '書式',
                            ')が',
                            bold, '混在',
                            'するセル',
                            superscript, '上付き',
                            superscript_purple, '文字')

## ファイルを閉じる
workbook.close()

上記のコードを実行すると、下図のようなxlsxファイルが出力されます。

キャプチャ.PNG

worksheetオブジェクトに対して、write_rich_string()メソッドを呼ぶと、リッチテキストで値を書き込むことができます。

補足

設定できる書式の種類

workbookオブジェクトに対して、add_format()メソッドを呼ぶと、返り値としてFormatオブジェクトが返ってきますが、このFormatオブジェクトに設定できる書式は、公式ドキュメントにいろいろ書かれていますので、そちらをご覧ください。(英語)

セル指定方法

上記コードでは、write_rich_string()メソッドの第1引数で'A1'というようなセル指定をしており、第2引数以降に、文字列や書式を設定しています。

代わりに、下記コードのように、行と列のインデックス番号で指定することもできます。第1引数は行番号(0始まり)、第2引数は列番号(0始まり)です。

## リッチテキストをA1セルに追加
worksheet.write_rich_string(3,4, # この場合、E4セルを指定していることになる
                            'いろんな',
                            red, 'フォント',
                            '(',
                            italic_underline, '書式',
                            ')が',
                            bold, '混在',
                            'するセル',
                            superscript, '上付き',
                            superscript_purple, '文字')

この場合、第3引数以降が、設定したい文字列や書式になります。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ctypesの変数についてのメモ

変数、ポインタの生成と読み書き

ライブラリの読み込み

import ctypes

通常の変数の生成

i = ctypes.c_uint32(10)  # unsigned int i = 10;
f = ctypes.c_float(25.4)  # float = 25.4;

生成した変数の値を取得

i.value  # 10
f.value  # 25.399999618530273

生成した変数への代入

i.value = 20
f.value = 14.2

生成した変数のポインタを取得

i_p = ctypes.pointer(i)
f_p = ctypes.pointer(f)

ポインタから変数を取得

i_p.contents
f_p.contents

ポインタから変数の値を取得

i_p.contents.value  # 20
f_p.contents.value  # 14.199999809265137

配列の生成と読み書き

1次配列の生成

i_arr = (ctypes.c_int32 * 3)()  # int i[3];

2次配列の生成

i_arr = ((ctypes.c_int32 * 4) * 3)()  # int i[3][4];

配列の読み書き

i_arr = (ctypes.c_int32 * 3)()  # int i[3];
i_arr[0] = 10
print(i_arr[0])  # 10

ctypesで扱える型の一覧

ctypesの型 Cの型 Pythonの型
c_bool _Bool bool (1)
c_char char 1文字のバイト列オブジェクト
c_wchar wchar_t 1文字の文字列
c_byte char int
c_ubyte unsigned char int
c_short short int
c_ushort unsigned short int
c_int int int
c_uint unsigned int int
c_long long int
c_ulong unsigned long int
c_longlong __int64 または long long int
c_ulonglong unsigned __int64 または unsigned long long int
c_size_t size_t int
c_ssize_t ssize_t または Py_ssize_t int
c_float float 浮動小数点数
c_double double 浮動小数点数
c_longdouble long double 浮動小数点数
c_char_p char * (NUL 終端) バイト列オブジェクトまたは None
c_wchar_p wchar_t * (NUL 終端) 文字列または None
c_void_p void * 整数または None

参考

https://qiita.com/everylittle/items/6e18ba23f38502c18f3e
https://docs.python.org/ja/3/library/ctypes.html
http://curlnoodle.hatenablog.com/entry/2013/12/30/221858

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AtCoder Beginner Contest 131解いてみた

はじめに

AtCoder Beginner Contest 131をといてみた
https://atcoder.jp/contests/abc131/tasks

自分より成績の良い友人の解答をお借りして自分が何が苦手でわかっていなかったかを考えてみる

A - Security

自分の解答

strings = list(input())
before_number = 100000
flag = False
for number in strings:
  #前の番号と今の番号が一致したら
  if before_number == int(number):
    flag = True
  else:
    before_number = int(number)

if flag == True:
  print("Bad")
else:
  print("Good")

友人の解答

str = input()
p = ""
result = "Good"
for s in str:
    if p == s :
        result = "Bad"
    p = s
print(result)

考えたこと

B - Bite Eating

やたらめったら文章量が多くて圧倒されてしまった
一つずつ解決して完答した

#N個のりんごの数 L:味の基準
N, L = map(int, input().split())

#普通のアップルパイの味
nomal_sum = 0
for number in range(1,N+1):
  nomal_sum = nomal_sum + (L + number -1)
#print("普通のアップルパイ",nomal_sum)

#一つ欠けたアップルパイのパターンを作る
#lost_sum = 0
#for number in range(1,N+1):
#  if number == 1:
#    print("1だよ")
#  else:
#    lost_sum = lost_sum + (L + number -1)
#print(lost_sum)

#一つ欠けたアップルパイのリストをつくる
list = []
lost_sum = 0
for number in range(1,N+1):
  for number2 in range(1,N+1):
    if number != number2:
      lost_sum = lost_sum + (L + number2 -1)
  list.insert(number, lost_sum)
  lost_sum = 0
#print("list",list)

# 差の絶対値を取る
minimal1 = 100000
ans = 0
for list_aji in list:
  #print("list_aji",list_aji)
  #print("minimal1",minimal1)
  #print("abs(list_aji - nomal_sum)",abs(list_aji - nomal_sum))
  if minimal1 >= abs(list_aji - nomal_sum):
    minimal1 = abs(list_aji - nomal_sum)
    ans = list_aji
print(ans)

友人の書いたコード

N, L = map(int, input().split())

list = [L+(i+1)-1 for i in range(N)]

list.sort(key=lambda x: abs(x))

del list[0]

print(sum(list))

C - Anti-Division

計算量さえ考えなければ正解だっただろうな。。。と思う
というかこれをどうやって計算量を少なくできるのかが全くわからなかった
とてもつらい

自分の解答

A, B, C, D = map(int, input().split())

count = 0
for i in range(A,B+1):
  #print("///////////")
  #print(i)
  if(i % C == 0 and i % D != 0): # 3で割り切れるが5で割り切れない
    #print("2で割り切れるが3で割り切れない")
    pass
  elif(i % D == 0 and i % C != 0): # 5で割り切れるが3で割り切れない
    #print("2で割り切れるが3で割り切れない")
    pass
  elif(i % C == 0 and i % D == 0): # 3で割り切れ、かつ5で割り切れる
    #print("2で割り切れるが3で割り切れる")
    pass
  else:
    #print("どれにもあてはまらない",i)
    count = count + 1
print(count)

友人の解答

def gcd(a, b):
    while b:
        a, b = b, a % b
    return a


def lcm(a, b):
    return a * b // gcd (a, b)

A, B, C, D = map(int, input().split())

b_num = B//C + B//D - B//lcm(C, D)
a_num = (A-1)//C + (A-1)//D - (A-1)//lcm(C, D)

print((B-A+1) -(b_num - a_num))

コードを改良した
最小公倍数や最大公約数を使うなんて思いもしなかった
ループで回してがんばるという脳筋プレイはやめたい
参考文献によるとfractionsモジュールにgcd関数があるとのことなので流用した

import fractions
def lcm(a,b):
  return a*b //fractions.gcd(a, b)

A, B,C,D = map(int, input().split())

b_num = B//C + B//D - B//lcm(C, D)
a_num = (A-1)//C + (A-1)//D - (A-1)//lcm(C, D)
print((B-(A-1))-(b_num-a_num))

参考文献

https://blog.panicblanket.com/archives/703

D - Megalomania

あり本でやったような問題だなと思った
アルゴリズム的には、一番仕事の締切が短いやつから片付けていくのがよいのだろうか?
全然とけなかった

自分の解答

N = int(input())
A = [list(map(int, input().split())) for _ in range(N)]
#A[0][0]仕事の時間 A[0][1]締切
print(A[0][0],A[0][1])
#知りたいことはすべての仕事を達成できるかどうか
#終了時間が最も早いものを選ぶ
most_last = 100000
time = 0

for number in range(0,N):
  print("締切",A[number][1])
  if most_last > A[number][1]:
    #一番小さい締切を更新
    most_last = A[number][1]
print(most_last)
for y, row in enumerate(A):
    try:
        pos = (y, row.index(most_last))
        break
    except ValueError:
        pass

print("pos",pos[0],pos[1])
#一番小さい締切の配列はとれる
print(A[pos[0]][pos[1]])

#時間を進めてその配列を削除させる

友人の解答

N = int(input())
jobs = []
for i in range(N):
    jobs.append(list(map(int, input().split())))

time = 0
result = "Yes"
jobs.sort(key=lambda x:x[1])

for job in jobs:
    time += job[0]
    if(time > job[1]):
        result = "No"
        break

print(result)

考えたこと

二重配列をうまいこと使いこなせなかった
sortとラムダ式をうまいこと使う必要があった
Pythonらしい書き方ができていないのが問題

こうやって二重配列にうまいこと入れれるのは学びになった

for i in range(N):
    jobs.append(list(map(int, input().split())))

このソートの仕方が学びになった
二重配列のソートをどうすれば良いのかわからなくて困っていた

jobs.sort(key=lambda x:x[1])
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

FLASK  キャラクターの行動メニューを表示する【Windows.ver】

目標:共通テンプレートを使って、ブラウザで下記のようにキティの行動が表示されるようにする
2019-06-22 (16).png

共通テンプレートの作り方はこちらの記事☞FLASK  共通テンプレートの作り方【Windows.ver】

1.行動の指示をだすためのファイルを作成
●新規ファィルを作成 ファイル名:Character_menu.py
●下記のようにコードを書く
2019-06-22 (18).png

2.新規でhtmlのファィルを作成
共通テンプレートのファィルlayout.htmlはすでに作成してあるので、それをextendsで引っ張ってくる
行動をhtmlの中に記述。

2019-06-22 (20).png

※ここまできたら、ブラウザでちゃんと表示するか確認をする!
2019-06-22 (16).png

しかし、リンクを押すとエラーになります!
なぜならリンク先を指定していないから。

リンク先に行動が表示されるようにコードを書いていく
2019-06-22 (25).png

action.htmlという新しいファィルを作成する
これはmenu.htmlをコピーして
コードを編集するとよい
2019-06-22 (26).png

ブラウザにアクセスすると
2019-06-22 (16).png

「自転車に乗る」と「タクシーに乗る」をそれぞれクリックすると
2019-06-22 (27).png

2019-06-22 (28).png

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Tornado(websocket)とVueを使ってTwitterのトレンドを表示する

出来上がったもの

こちら
ソースコード

Tornadoについて

公式ドキュメント
Facebookにより開発されているPythonで書かれたWebフレームワーク。
ノンブロッキングI/Oを使用しているので、WebSocketなど長期接続を必要とするアプリケーションに最適だとドキュメントで紹介されています。

アプリケーションの概要

TwitterApiでトレンドを一定間隔で取得websocketでクライアントにプッシュVue.jsでリストレンダリング

という単純なものです。

サーバーサイド

公式のwebsocketデモアプリを少し改変した程度です。

トレンドを一定間隔で取得する

app.py
api = tweepy.API(auth)
regional_id = {}
for place in api.trends_available():
    if place['countryCode'] == 'JP':
        regional_id[place['name']] = place['woeid']
JP = regional_id['Japan']

def loop_in_period_interval():
    PERIOD = 30
    ioloop = tornado.ioloop.IOLoop.current()
    ioloop.add_timeout(time.time() + PERIOD, loop_in_period_interval)
    trends = []
    for idx, trend in enumerate(api.trends_place(JP)[0]['trends'], 1):
        value = {
            "rank": str(idx),
            "name": trend["name"],
            "volume": trend["tweet_volume"],
            "url": trend["url"]
        }
        trends.append(value)
    TwitterTrendWebSocketHandler.trends_cache = trends
    json_str = json.dumps(trends)
    TwitterTrendWebSocketHandler.send_updates(json_str)

loop_in_period_intervalで30秒間隔でトレンドを取得しています。
なお、この部分はこちらを参考にさせていただきました。

クライアントにプッシュ

app.py
class TwitterTrendWebSocketHandler(tornado.websocket.WebSocketHandler):
    waiters = set()
    trends_cache = []

    def get_compression_options(self):
        return {}

    def open(self):
        TwitterTrendWebSocketHandler.waiters.add(self)
        trends = json.dumps(
            TwitterTrendWebSocketHandler.trends_cache
        )
        self.write_message(trends)

    def on_close(self):
        TwitterTrendWebSocketHandler.waiters.remove(self)

    @classmethod
    def send_updates(cls, trends):
        logger.info("sending message to %d waiters", len(cls.waiters))

        for waiter in cls.waiters:
            try:
                waiter.write_message(trends)
            except:
                logger.error("Error sending message", exc_info=True)

websocketのhandlerです。
接続時にopenメソッドでクラス変数waitersにクライアントが追加されます。
先程のloop_in_period_interval関数内でクラスメソッドsend_updatesが実行され各クライアントにブロードキャストされます。

app.py
if os.getenv("HEROKU") is None:
    dotenv_path = os.path.join(os.path.dirname(__file__), ".env")
    load_dotenv(dotenv_path)
    port = 8888
else:
    port = int(os.environ.get("PORT", 5000))

CONFIG = os.environ

HEROKUを使うにあたって.envファイルで環境変数を切り替えています。
また、こちらのプラグインを使うとheroku config:pushコマンドでローカルの.envファイルの内容をHEROKUの環境変数に設定できるのでおすすめです。

クライアントサイド

単純なアプリなのでvue-cliを使わずCDNを使っています。
その際、注意すべき点として記法の衝突があります。
Tornadoのテンプレートで使う{{}}がVueのマスタッシュ記法と同じになってしまいエラーが発生します。

app.js
const vm = new Vue({
  el: '#app',
  // 略
  delimiters: ["<%","%>"], //{{ }} から <% %>に変更
})

なので、このようにVue側でデリミタを変更する必要があります。

リストレンダリングにトランジションを追加する

テーブルに適用する際

index.html
<transition-group tag="tbody" id="left">
  <!-- 1 to 25 -->
    <tr v-for="trend in upTo25" :key="trend.name" v-cloak>
      <th><% trend.rank %></th>
      <td><a :href="trend.url" class="has-text-grey-darker"><% trend.name %></a></td>
      <td><% trend.volume %></td>
    </tr>
 </transition-group>

公式サイトにあるように、transition-groupタグを使い、tagtbodyを指定したのですが動作しませんでした。

index.html
<tbody is="transition-group" id="left">
  <!-- 1 to 25 -->
    <tr v-for="trend in upTo25" :key="trend.name" v-cloak>
      <th><% trend.rank %></th>
      <td><a :href="trend.url" class="has-text-grey-darker"><% trend.name %></a></td>
      <td><% trend.volume %></td>
    </tr>
</tbody>

こうすることでうまく動作しました。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Selenium for Python find_elementの実行速度をざっくりと比較する

はじめに

Seleniumで自動化に挑戦してみました。
個人的に使用するには十分なものが作れました。
しかし、実行速度が気になりました。
調べてみたらfind_elementを繰り返し実行するだけで結構な時間がかかるようです。
そこで、find_elementの使い方で実行速度が変わるのか、どの方法を使えばよいか調べてみることにしました。
あんまり厳密な方法ではなくてざっくりとした結果ですが記事にしてみます。

実行環境

Python 3.7.3
selenium 3.141.0
Google Chrome: 75.0.3770.100(Official Build) (64 ビット)
ChromeDriver 75.0.3770.90
Firefox: 67.0.4 (64 ビット)
geckodriver 0.24.0 ( 2019-01-28)

実験

テストサイト

テストサイトとしてgoogleを選びました。
余計なものを省くと以下のようなhtmlになります。
これのinputタグをfind_elementを使って取得することとします。

html
<html itemscope="" itemtype="http://schema.org/WebPage" lang="ja">
  <body jsmodel=" " class="hp vasq big" id="gsr">
    <div class="ctr-p" id="viewport">
      <div class="jhp big" id="searchform">
        <form class="tsf nj" action="/search" style="overflow:visible" id="tsf" method="GET" name="f" onsubmit="return q.value!=''" role="search">
          <div jsmodel="vWNDde" jsdata="MuIEvd;;Cjj2lE">
            <div jscontroller="mvYTse" class="A8SBwf" jsaction="DkpM0b:d3sQLd;IQOavd:dFyQEf;XzZZPe:jI3wzf;Aghsf:AVsnlb;iHd9U:Q7Cnrc;f5hEHe:G0jgYd;vmxUb:j3bJnb;R2c5O:LuRugf;qiCkJd:ANdidc;NOg9L:HLgh3;uGoIkd:epUokb;zLdLw:eaGBS;rcuQ6b:npT2md">
              <div class="RNNXgb" jsname="RNNXgb">
                <div class="SDkEP">
                  <div jscontroller="iDPoPb" class="a4bIc" jsname="gLFyf" jsaction="h5M12e;input:d3sQLd;focus:dFyQEf;blur:jI3wzf">
                    <input class="gLFyf gsfi" maxlength="2048" name="q" type="text" jsaction="paste:puy29d" aria-autocomplete="both" aria-haspopup="false" autocapitalize="off" autocomplete="off" autocorrect="off" role="combobox" spellcheck="false" title="検索" value="" aria-label="検索" data-ved="0ahUKEwjP1420wfziAhXIebwKHfF-A5oQ39UDCAQ">
                  </div>
                </div>
              </div>
            </div>
          </div>
        </form>
      </div>
  </body>
</html>

対象ドライバー

  1. ChromeDriver (google chrome)
  2. geckodriver (firefox)

find_elementの引数

  1. DevToolsから得られたXPath
  2. 簡潔なXPath
  3. 冗長なXPath
  4. クラス名
  5. Name属性
  6. 簡潔なCSSセレクタ
  7. 冗長なCSSセレクタ

ソース

python
import functools
import time

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC


def stopwatchPrint(func):
  @functools.wraps(func)
  def wrapper(*args, **kwargs):
    start = time.time()
    result = func(*args, **kwargs)
    end = time.time()
    print("{}: {}".format(func.__name__, end - start))
    return result
  return wrapper


def test(driver, by, value):
  driver.get("https://www.google.com/")
  wait = WebDriverWait(driver, 30)
  wait.until(EC.visibility_of_element_located((By.ID, "viewport")))
  element = getElement(driver, by, value)
  # print(element)
  element.send_keys("虎の敷物")
  element.submit()


@stopwatchPrint
def getElement(driver, by, value, t=1000):
  print("{}, {}".format(by, value))
  for i in range(t):
    element = driver.find_element(by, value)
  return element


InputXpathByDevTools = "//*[@id='tsf']/div[2]/div/div[1]/div/div[1]/input"
InputXpath1 = "//input[@name='q']"
InputXpath2 = "//body[@id='gsr']/div[@id='viewport']/div[@id='searchform']/form[@id='tsf']/div[@jsmodel='vWNDde']/div[@class='A8SBwf']/div[contains(@class, 'RNNXgb')]/div[@class='SDkEP']/div[@class='a4bIc']/input[@name='q']"
InputClass = "gLFyf"
InputName = "q"
# InputCSS1 = "input.gLFyf"
InputCSS1 = "input[name=q]"
InputCSS2 = "body#gsr div#viewport div#searchform form#tsf div[jsmodel=vWNDde] div.A8SBwf div.RNNXgb div.SDkEP div.a4bIc input[name=q]"

if __name__ == '__main__':
  try:
    #driver = webdriver.Chrome('\\webdriver\\chromedriver_win32\\chromedriver.exe')
    driver = webdriver.Firefox('\\webdriver\\geckodriver-v0.24.0-win64')

    test(driver, By.XPATH, InputXpathByDevTools)
    test(driver, By.XPATH, InputXpath1)
    test(driver, By.XPATH, InputXpath2)
    test(driver, By.CLASS_NAME, InputClass)
    test(driver, By.NAME, InputName)
    test(driver, By.CSS_SELECTOR, InputCSS1)
    test(driver, By.CSS_SELECTOR, InputCSS2)

  except Exception as e:
    print("{}: {}".format(type(e), e))

  finally:
    time.sleep(2)
    driver.quit()

結果

数回繰り返した結果、引数を変えても実行速度は変わらないようです。
また、geckodriverの方が、ChromeDriverより実行速度が速いようです。

つまり、

  • 引数には簡潔で分かりやすい記述をする
  • 問題がないようならばgeckodriverを選ぶ

とすれば良いようです

ChromeDriver

実行結果の抜粋
28秒前後で動作します。
ただし、初めに呼んだものが明らかに実行速度が速いです。
この引数を最後に呼んでみると同じように28秒程度で動作しますので引数の問題ではなくて実行順の問題のようです。
なにかソースに間違いがあるのかもしれません。

初稿では、ChromeとChromeDriverのバージョンが合っていなかったのですが合わせてみても結果は特に変わらなかったです。

xpath, //*[@id='tsf']/div[2]/div/div[1]/div/div[1]/input
getElement: 19.230003356933594

xpath, //input[@name='q']
getElement: 25.615001678466797

xpath, //body[@id='gsr']/div[@id='viewport']/div[@id='searchform']/form[@id='tsf']/div[@jsmodel='vWNDde']/div[@class='A8SBwf']/div[contains(@class, 'RNNXgb')]/div[@class='SDkEP']/div[@class='a4bIc']/input[@name='q']
getElement: 29.41499948501587

class name, gLFyf
getElement: 29.305000066757202

name, q
getElement: 28.85899519920349

css selector, input[name=q]
getElement: 28.90398097038269

css selector, body#gsr div#viewport div#searchform form#tsf div[jsmodel=vWNDde] div.A8SBwf div.RNNXgb div.SDkEP div.a4bIc input[name=q]
getElement: 29.159016132354736

geckodriver

実行結果の抜粋
10秒前後で動作します。
geckodriverは実行速度が速いためかsubmitの結果が表示されずに次に行ってしまいます。
しかし、実験の本質と関係ないので無視しました。
(time.sleepを入れる、画面遷移を確認する等で正常に機能します。)

xpath, //*[@id='tsf']/div[2]/div/div[1]/div/div[1]/input
getElement: 9.75801420211792

xpath, //input[@name='q']
getElement: 9.892000198364258

xpath, //body[@id='gsr']/div[@id='viewport']/div[@id='searchform']/form[@id='tsf']/div[@jsmodel='vWNDde']/div[@class='A8SBwf']/div[contains(@class, 'RNNXgb')]/div[@class='SDkEP']/div[@class='a4bIc']/input[@name='q']
getElement: 11.554003238677979

class name, gLFyf
getElement: 10.823017835617065

name, q
getElement: 11.586012840270996

css selector, input[name=q]
getElement: 10.772995471954346

css selector, body#gsr div#viewport div#searchform form#tsf div[jsmodel=vWNDde] div.A8SBwf div.RNNXgb div.SDkEP div.a4bIc input[name=q]
getElement: 11.920017004013062

最後に

Seleniumは、大分癖がありますね。
ChromeDriverで動かしていましたがgeckodriverに変えることとします。
大分、実行速度が変わりそうです。
また、わざわざ冗長に書いていたのを簡潔にしようと思いました。
またやることが増えた(´・ω・`)

追記

既存のプログラムをgeckodriverにしたら6倍ほど速くなりました。(*´ω`*)

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Pythonで「素数日」を求めたら処理が長すぎて日が暮れそうになった

はじめに

時々Twitter等で「今日は素数日!」のようなツイートをみかけます。
これは、年月日(西暦)を8桁の数に置き換えたときに、それが素数になる日を指します。

例:2019年5月23日 → 20190523(素数)
  2019年7月19日 → 20190719(素数)

ので、Pythonの練習のため、素数日を求めるコードを書いてみます。

準備

何も考えずにコードを書くと、存在しない日付を表示してしまいます。
考えなければいけないのは以下の項目。

  • 月ごとの日数
    • 当然ですが、月ごとに日数が違うので事前に設定しておく必要があります。
    • なので事前に下記のように各月の日数をリスト化しておきましょう。
day = [31,28,31,30,31,30,31,31,30,31,30,31]
  • うるう年
    • うるう年のみ2月が29日間になるのでここも考慮に入れる必要があります。
    • うるう年の判定条件は以下の通りです
      • 西暦で示した年が4で割り切れる年はうるう年です
      • 西暦で示した年が100で割り切れる年はうるう年ではありません
      • 西暦で示した年が400で割り切れる年はうるう年です

上記を考慮した、うるう年を判定する関数を事前に定義しておきます。

def Uru(year):
    if year % 4 == 0:
        if year % 100 == 0:
            if year % 400 == 0:
                return 1
            else:
                return 0
        else:
            return 1
    else:
        return 0

返り値が0のときが普通の年、1のときがうるう年。
もっとすっきりと記述する方法あると思いますが、自分の能力ではこれが限界です。
加えて、うるう年のときの日数リストも作っておきます。

day_uru = [31,29,31,30,31,30,31,31,30,31,30,31]

実装したコード

上記準備をもとに下記のコードをとりあえず書きました。

import math
#各部品
year = range(0,10000) #西暦元年から西暦9999年まで調べたい
month = [1,2,3,4,5,6,7,8,9,10,11,12] #月のリスト
day = [31,28,31,30,31,30,31,31,30,31,30,31]
day_uru = [31,29,31,30,31,30,31,31,30,31,30,31]
prime_day = [] #素数日を格納するリスト

#うるう年判定
def Uru(year):
    if year % 4 == 0:
        if year % 100 == 0:
            if year % 400 == 0:
                return 1
            else:
                return 0
        else:
            return 1
    else:
        return 0

for i in year:
    if Uru(i) == 0: #うるう年じゃないとき
        for j in month:
            for k in range(1,day[j-1]+1):
                if k % 2 == 0: #日が偶数の時点で素数にはならないのでここで一度判定
                    continue
                date = i*10000 + j*100 + k #8桁生成
                date_half = math.ceil(date / 2)
                wari = [l for l in range(3, date_half)]           
                for m in wari[0::2]: #2の倍数を除いた数で対象のdateをひたすら割る 
                    if date % m == 0:
                        break
                    else:
                        if (m == date_half or m == date_half -1):
                            prime_day.append(date)
    else: #うるう年
        for j in month:
            for k in range(1, day_uru[j-1]+1):
                if k % 2 == 0:
                    continue
                date = i*10000 + j*100 + k
                date_half = math.ceil(date / 2)
                wari = [l for l in range(3, date_half)]          
                for m in wari[0::2]:
                    if date % m == 0:
                        break
                    else:
                        if (m == date_half or m == date_half -1):
                            prime_day.append(date)

print(prime_day)

これで一度実行したんですが、CPUファンの回転数が「ファーン↑↑」と上がったっきり結果が帰ってきませんでした。
冷静に考えればわかることですが、9999年分判定すると9999*365=3,649,635 日分を判定することになります。
日が偶数の日は処理がすぐ終わる(と思う)ので、実際にはその半分。
それでも、更にそこから素数かどうかの判定が都度入るので、PCの計算が追いつかないんですね。。。
こればっかりは、効率的な素数判定のアルゴリズムを勉強しないとどうにもならないので、
諦めて指定した年の素数日判定するコードにしたいと思います。

import math

year = input("input year:") #調べたい年を1つ入力
month = [1,2,3,4,5,6,7,8,9,10,11,12]
day = [31,28,31,30,31,30,31,31,30,31,30,31]
day_uru = [31,29,31,30,31,30,31,31,30,31,30,31]
prime_day = []

def Uru(year):
    if year % 4 == 0:
        if year % 100 == 0:
            if year % 400 == 0:
                return 1
            else:
                return 0
        else:
            return 1
    else:
        return 0

i = int(year)
if Uru(i) == 0:
    for j in month:
        for k in range(1,day[j-1]+1):
            if k % 2 == 0:
                continue
            date = i*10000 + j*100 + k
            date_half = math.ceil(date / 2)
            wari = [l for l in range(3, date_half)]          
            for m in wari[0::2]:
                if date % m == 0:
                    break
                else:
                    if (m == date_half or m == date_half -1):
                        prime_day.append(date)
else:
    for j in month:
        for k in range(1, day_uru[j-1]+1):
            if k % 2 == 0:
                continue
            date = i*10000 + j*100 + k
            date_half = math.ceil(date / 2)
            wari = [l for l in range(3, date_half)]          
            for m in wari[0::2]:
                if date % m == 0:
                    break
                else:
                    if (m == date_half or m == date_half -1):
                        prime_day.append(date)

print(prime_day)

試しに2019年でコードを動かしてみます。
これでも結果が返ってくるのに1分かかりました。

[20190221, 20190227, 20190301, 20190319, 20190323, 20190421, 20190523, 20190529, 20190601, 20190613, 20190719, 20190811, 20190823, 20190913, 20191009, 20191027, 20191109, 20191117, 20191231]

というわけで、今年は素数日が19日あるみたいです。

最後に

大晦日が素数日ってなんかエモいやん?

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Python】Dashのcallbackにアニメーションをつける

Dash Loading Component

ezgif.com-crop.gif

背景

Dashの可視化アプリケーションの描画に、loadingアニメーションをつけたいと思いました.

ちなみに、デフォルトだと以下のように何も変化がなく、inputを検知したことが伝わりにくくなってしまいます.

default_loading.gif

  • 環境

    • macOSX Mojave version 10.14,3
    • Python 3.6.1
    • R version 3.5.3
    • 実行環境はlocalで
  • 仕様

    • Dropdownのinputを受けてから2秒待機してcomponentを描画する
    • 2秒間の間にアニメーションを表示する

方法

Loading Componentで紹介されているdash_core_components.Loading()を使います.

アニメーションのあとで表示させたいcomponentをdcc.Loading()childrenとして与えます.

app.py
import dash
import dash_html_components as html
import dash_core_components as dcc
import time

from dash.dependencies import Input, Output

app = dash.Dash(__name__)
common_style = {'position': 'relative', 'width': '100%',
                'font-family': 'Dosis', 'text-align': 'center'}

app.layout = html.Div(
    children=[
        html.H1("Dash app with loading state", style={'margin-bottom': '10%'}),
        dcc.Dropdown(
            id='my-dropdown',
            options=[
                {'label': 'Cactus',
                 'value': 'https://image.flaticon.com/icons/svg/874/874979.svg'},
                {'label': 'Clownfish',
                 'value': 'https://image.flaticon.com/icons/svg/875/875011.svg'},
                {'label': 'Crab',
                    'value': 'https://image.flaticon.com/icons/svg/875/875010.svg'}
            ],
            value='https://image.flaticon.com/icons/svg/874/874979.svg'
        ),
        dcc.Loading(id="loading-1",
                    children=[
                        html.Div(id='output-container',
                                 )
                    ],
                    style={"margin": "10%"},
                    type="default"),
    ],
    style=common_style
)


@app.callback(
    Output('output-container', 'children'),
    [Input('my-dropdown', 'value')])
def input_triggers_spinner(value):
    time.sleep(2)
    return html.Img(src=value, height="30%", width="30%", style={"margin": "10%"})


if __name__ == "__main__":
    app.run_server(debug=False)

結果

ezgif.com-crop.gif

その他

spinnerの種類は上のdefaultを含めて5種類用意されているようです.

  • graph

graph.gif

  • cube

cube.gif

  • circle

circle.gif

  • dot

dot.gif

ぜひお試しください!

参考

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Pythonで画像ファイルを扱う際のTips

Pythonでネット上にある画像をダウンロードして、Twitterなどのapiを使ってアップロードすることがたまにあるのですが、一度ローカルストレージにファイルを保存してからアップロードのが通常かと思います。

コードにするとこんな感じ。

import requests

imgUrl = 'https://www.python.org/static/img/python-logo.png'
r = requests.get(imgUrl)
with open('sample.png', 'wb') as f:
    f.write(r.content)

ストレージにPythonのロゴの画像がダウンロードされるはずです。

で、今回はストレージに画像を保存しないでそのままアップロードする方法を見つけたのでシェアハピします。

標準ライブラリのio.BytesIOに画像のバイナリデータを渡してあげるだけです。

import requests 
from io import BytesIO

imgUrl = 'https://www.python.org/static/img/python-logo.png'
r = requests.get(imgUrl)
img = BytesIO(r.content)

変数imgにはインメモリーで扱えるファイルオブジェクトが入ります。これにより保存する必要がないファイルの場合にはストレージを圧迫しなくて済みます。GAEなどのread-onlyなPaaSなどで画像ファイルを扱う際にはめちゃくちゃ便利です。

試しにTweepyで画像をアップロードしてみます。

import tweepy
import requests 
from io import BytesIO

consumer_key = 'your_consumer_key'
consumer_secret = 'your_consumer_secret'
access_key = 'your_access_key'
access_secret = 'your_access_secret'
auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
auth.set_access_token(access_key, access_secret)
api = tweepy.API(auth)

# 通常
imgUrl = 'https://www.python.org/static/img/python-logo.png'
r = requests.get(imgUrl)
with open('sample.png', 'wb') as f:
    f.write(r.content)

api.update_with_media('sample.png', status='test')


# BytesIOを使う場合
imgUrl2 = 'https://www.python.org/static/img/python-logo.png'
r2 = requests.get(imgUrl2)
img2 = BytesIO(r2.content)

result_img = api.media_upload(filename='sample2.png', file=img2)
api.update_status(status='test2', media_ids=[result_img.media_id])

通常ローカルストレージにある画像指定してアップロードするメソッドである、update_with_mediaではファイルオブジェクトを扱うことができないのでmedia_uploadメソッドを使います。これによりアップロードされた画像のmedia_idを通常のツイートメソッドであるupdate_statusのmedia_idsの引数に渡すことでツイートが完了します。

ちなみにですがTweepyの公式リファレンスのupdate_with_mediaメソッドの欄を読むと

Deprecated: Use API.media_upload() instead. Update the authenticated user’s status. Statuses that are duplicates or too long will be silently ignored.
(非推奨:代わりにAPI.media_upload()を使用してください。 認証済みユーザーのステータスを更新します。 重複している、または長すぎる状況は黙って無視されます。)(Google翻訳)

だそうです。update_with_mediaは画像を一枚アップロードするだけなら一行で済むので便利でしたが、今後はmedia_uploadを使ったほうが良さそうです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

プログラミング完全初心者がChainerでディープラーニングを学んでみた

環境

この記事では、Python3.6以上であることが前提です。
実行はGoogle Colaboratory というサービスを利用し、ブラウザ上で実行しています。
Chainerページ: 1.はじめに-ディープラーニング入門

学んだこと

はじめは型(type)の説明があり、次に算術演算子(+,-,*,/)を学びました。
メゾット(method)format()list tuple dictionaryなどもありました。
僕みたいな完全な初心者にもわかるように、一つ一つ丁寧に説明があり、とてもすすめやすかったです。
他にもif文for文などpythonのほぼすべてを学ぶことができるので、プログラミングが全くわからない状態でディープラーニングをやってみたいというかたにおすすめです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Python 指定の単語を含む文章を抽出する関数

目次

1,内容
2,コード
3,終わりに

内容

ある文章から指定の単語を含む文章をヌキ出したく、悶々としていた夏の思ひで。
オッサンになりレベルアップした結果、遂に完全体になりました。
まあ、とりあえずコード実行してミソ。

コード

関数
import re
def extract_sentence_by_match_word(base_sentence, match_word, stop_signs):
    # 指定の単語以前をstop_signsまで抽出する
    get_back_sentence = re.search(f"(.*)(?={match_word})(.*?)({stop_signs})", base_sentence).group()

    # 抜き出した単語を逆順にする
    rev_sentence = get_back_sentence[::-1]

    # 逆順にし、stop_signsから次のstop_signsまで抽出する
    get_rev_sentence = re.search(f"({stop_signs})(.*?)({stop_signs})", rev_sentence).group()

    # もう一度逆順にし、base_sentenceから除外したい文章を抽出する
    extract_words = get_rev_sentence[::-1]
    return extract_words

コード動かすと結構理解しやすい(図解とかゲロ面倒だからやらぬぅ)

サンプルコード

サンプルコード
## 対象の文章
base_sentence = """
オートアート

77425 1/18 西部警察 「マシンRS-1」 放送開始40周年記念モデル 
画像はメーカーの見本です。
(2019年 12月以降発売・入荷日が分かり次第、ご連絡させて頂きます。) 
(発売日が延期となる場合がございます。発売日が延期となった場合は、連絡掲示板でご連絡させて頂きます。) 
(落札後1週間以内にオーダーフォーム入力して下さい。)
(落札後1週間以内にオーダーフォーム入力が無い場合は落札者都合での取消となります。)
(お支払い方法ですが、Yahoo!かんたん決済かジャパンネット銀行でのお支払いの場合は、落札後1週間以内にお支払い下さい。) 
(予約商品となります。落札後キャンセル対応はできませんので、あらかじめご了承下さい。) 


 1979年10月の第一作テレビシリーズ放送開始から数えて2019年でちょうど40年、今なお絶大な人気を誇るアクション刑事ドラマ「西部警察」。劇中に登場したスーパー・パトカー「RS軍団」は、当時の最強モデル「日産 スカイライン(DR30)」をベースに最高時速250km/hオーバーにまで改造され、ドラマでの重要な役割を果たしその人気を支えました。今回多くのご要望にお応えし、オートアートの1/18スケールモデルとして2014年に発売後即完売となった「RS軍団」最速の『マシンRS-1』が約5年ぶりに登場。再モデル化にあたっては、新品番とし、再度入念な資料検証を行いモデル各部を改良、内外装のスペシャルパーツもよりリアルに再現しました。フル開閉モデルならではのギミックも存分にお楽しみ頂けます。さらに放送開始40周年を記念し、ディスプレイケース(別売)の台座に貼付したり、モデルと一緒に展示するとスペシャル感がアップする金属製の『40周年記念プレート』が付属します。 ●開閉式二連装20ミリ機銃●急加速装置アフターバーナー●ルーフ大型警光灯●メッシュホイール●エアアウトレット●エアロパーツ●フロントフォグランプ&赤色灯●助手席大型コンピューター●特殊無線機●ドライバーズシート●ステアリングホイール●「放送開始40周年記念プレート」(金属製・約10×2㎝)付属 ※この商品は日本限定発売モデルです。 石原プロモーション

定価¥24800(税抜)
"""

## 指定の単語
match_words = [
    "年",
    "税抜",
    "限定",
    "¥",
    "定価",
    "支払"
]

## 文章を区切る記号
stop_signs = [
    "【",
    " ",
    "。",
    ".$",
    "^.",
    "\n"
]
stop_signs = "|".join(stop_signs)
print("*" * 100)
print(base_sentence)
print("*" * 100)
for match_word in match_words:
    print()
    print("*" * 100)
    print(f"関連の単語 : {match_word}")
    print("抽出した文章 : ")
    print(extract_sentence_by_match_word(base_sentence, match_word, stop_signs))
    print("*" * 100)

とりあえず動かすのだ ファファファファ

大元の文章

sample1.png

色々こねくり回して、指定の単語を含む文章を取得

スクリーンショット 2019-06-22 16.57.30.png
上記はわかりやすくするため、match_wordを★に変えて表示させてます。
今回で言うと【年】というのがmatch_wordであり、その単語の前後の文章をヌキ出します。
プロなら一発で指定の単語の前後をヌキ出せるんでしょうが、
イナカモンのワイにはわからんかったので、文章をひっくり返し、
開始stop_signsから次のstop_signsまで取得しました。

そして、その後逆順にすると正常な文章が返ってきて、一件落着となります。

終わりに

全然エラー対策等はしてないが、一旦終了。
これで様々な文章を抽出および削除等が可能になったのが嬉しいし、
初めて汎用性のある関数を作れた気がするし、データ分析官のお役に立てればなにより。

参考サイト
http://straylight-engineer.blogspot.com/2014/01/blog-post.html
https://note.nkmk.me/python-re-match-search-findall-etc/

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

MiniPC ✕ DL ✕ Drone

この記事は、2019年07月13日(土) に名古屋駅至近で開催の「ディープラーニングガジェット品評会」の発表用資料です。

ディープラーニングガジェット品評会
https://connpass.com/event/129065/


1.はじめに


1−1.PINTO何者?


ふざけたことばかりやってます。
MultiStick MultiTPU.jpg


1−2.本日のネタ

  • 小型PC (GPUなし)
  • ドローン
  • ディープラーニング (Pose Estimation)

 ↓で、

爆速ガジェットを組みたい


GPU つかわない
ココが飛び出てるのがヤダ
   ↓
nano.png
発売直後に購入してまだ電源1度も入れていない


2.構成


2−1.小型PC

GPD Pocket 2 (超高価)
良い子はぜったいマネして買わないように 0001_GPD.jpg

スペック スペック スペック
OS Ubuntu Mate 18.04 GPU Intel HD 615 ストレージ 128 GB eMMC
CPU Intel Core m3-yY30 ディスプレイ 7インチ IPS
ゴリラガラス4
バッテリー 8時間
メモリ 8GB 解像度 1920x1200 重量 510g

2−2.ドローン

Tello
0002_Tello.jpg0003_Tello.jpg

  • Pythonで動かせる
  • 安価
  • 安全
  • おもちゃ

2−3.ディープラーニング

Pose Estimation (MobileNetV2)

  • 軽量 (2 MB 〜 9 MB)
  • 速い (10 FPS 〜 30 FPS)
  • 精度ボチボチ

3.MobileNetV2 based Pose Estimation 動画デモ


3−1.OpenVINOあり + CPU推論

3−2.OpenVINOなし + GPU (NVIDIA GTX 1070) 推論


4.OpenVINO


全体像
deep-learning-inference-intel-processor-fig1.jpeg


もうちょっとシンプルに
workflow_steps.png


推論
integration_process.png


5.OpenVINO・CPU/GPU/VPU スピード比較

①:OpenVINOなし + GPU (NVIDIA GTX 1070) 推論
②:OpenVINOあり + CPU (x86) 推論
③:OpenVINOあり + GPU (Intel HD 650) 推論
④:OpenVINOあり + VPU (Neural Compute Stick) 推論
⑤:OpenVINOなし + CPU (x86) 推論

※ TPUはUSB3.0で圧倒的なパフォーマンス


6.様々なデバイスによる性能比較

完璧な比較ブログが公開されている。
1. Google Coral Edge TPU vs NVIDIA Jetson Nano: A quick deep dive into EdgeAI performance - Sam Sterckval 氏
2. dd_performances - Github - jolibrain


7.PINTOのこだわり

  • 安定性
  • 調達性
  • 汎用性
  • GPU / VPU / TPU(ASIC) 使わない
    • 消費電力
    • 発熱
    • 取り回しのしにくさ
  • CPU単体で極限まで早く
  • インタプリタの限界へ

7−1.安定性

  • OpenVINO + CPU
    • オンボード稼働による安定性
    • 処理負荷のコア分散
    • CPU負荷高め
  • GPU/VPU
    • 物理インタフェース介在によるレイテンシ
    • 物理インタフェースの不安定さ
    • 発熱によるスロットリング

7−2.調達性

  • OpenVINO + CPU
    • 市販の普通のノートPCで十分
    • 即納
  • GPU/VPU搭載の開発ボード
    • 技適
    • 納期

7−3.汎用性

  • OpenVINO + CPU
    • パフォーマンス控えめ
      • だけどPCは近所の量販店でも調達できる
        • 事務機としても使用できる
  • GPU/VPU搭載の開発ボード
    • 何やら怪しい
      • 特定用途に寄りがち

8.本日のガジェット

空撮ダンスダンスレボリューション



9.ハマったこと

  1. Flask 分からん!!
  2. Drone が10分ぐらいでオーバーヒートしてしまう
  3. Wi-Fiがたまに不安定
  4. ジェスチャーの判定がとても難しい
  5. マウス壊れた
  6. 酷使しすぎてキーボードの EM- が壊れた

10.本当は。。。


  • ラズパイ + Edge TPU Accelerator で爆速ガジェットが作りたかった
  • ResNet-50で性能改善を図りたい
  • 3D-PoseEstimation にチャレンジしたい
  • ジェスチャーでDrone操作できるようにしたい

  • Brandonさんの Myriad X 搭載ラズパイHatで爆速ガジェットが作りたかった (カメラ画像を直接Xへインタフェースするらしい)
    D71a_htUIAEPgtr.jpg

11.さいごに

FireShot Capture 053 - kodamap - Qiita - qiita.com.png
本日のガジェットは @Kodamapさん の協力を得て作成されています。 というか、ほぼ @Kodamapさんの功績です。
とても助かりました! ありがとうございます!
https://qiita.com/kodamap
https://github.com/kodamap


ご清聴有難うございました。


コレ欲しい。。。 ラズパイZeroクラスタ化ハット
Clster_HAT_v2_4_of_4_1024x1024.jpg
https://www.notebookcheck.net/Raspberry-Pi-Combine-a-Raspberry-Pi-with-up-to-4-Raspberry-Pi-Zeros-for-less-than-US-50-with-the-Cluster-HAT.426998.0.html

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Chainer Tutorial 13章の[6]のコードがそのままだとうまく動かなかったのでメモ

題目の通り、Chainer Tutorial 13章の[6]のコードでエラーが出たので、修正した内容をメモしておきます。(2019年6月22日時点)

ちなみにPythonのバージョンは3.6.8です。

# d y / d h1
dydh1 = w2

# d h1 / d u1
dh1du1 = h1 * (1 - h1)

# d u_1 / d w1
du1dw1 = x

# 上から du1 / dw1 の直前までを一旦計算
dLdu1 = dLdy * dydh1 * dh1du1
dLdu1 = dLdu1[None]

# du1dw1は (3,) というshapeなので、g_u1w1[None]として(1, 3)に変形
du1dw1 = du1dw1[None]

# dL / dw_1: 求めたい勾配
dLdw1 = dLdu1.T.dot(du1dw1)

print(dLdw1)

真ん中らへんにある以下のコードを挿入しただけです。

dLdu1 = dLdu1[None]
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

FLASK  共通テンプレートの作り方【Windows.ver】

共通テンプレートの作り方

  1. templetes フォルダにindex.htmlの内容をコピーして新しいファイルlayout.htmlを作成

※index.htmlの内容とは
2019-06-22 (3).png

このコードを編集してlayout.htmlに共通テンプレートを作っていきましょう!

2019-06-22 (8).png

<body></body>の中に
<P>共通テンプレート</p>
{% block content %}
{% endblock %}

次にindex.htmlを開いて
2019-06-22 (11).png

<head><head/>のヘッダーの中身を削除
{% extends "layout.html" %}で共通テンプレートのlayout.htmlをよびだす
{% block content %}と記載。これより先のコードを
layout.htmlの{% block content %}の部分に埋め込むイメージ

コードの末は
{% endblock %}

ブラウザで表示すると

共通テンプレートと表示される
埋め込んだコードの文章が表示される
2019-06-22 (12).png

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Flask日本語チュートリアルが動かない

Flask日本語チュートリアルをやってみて、以下のようなエラーが出ませんでしたか?

ModuleNotFoundError: No module named 'flask.ext'
sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) no such table: entries
[SQL: SELECT entries.id AS entries_id, entries.title AS entries_title, entries.text AS entries_text 
FROM entries]
(Background on this error at: http://sqlalche.me/e/e3q8)
sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) no such table: entries
[SQL: INSERT INTO entries (title, text) VALUES (?, ?)]
[parameters: ('title', 'text')]
(Background on this error at: http://sqlalche.me/e/e3q8)

日本語チュートリアルの罠

この日本語チュートリアルサイト、バージョンが0.5.1なんですよね。

このサイトもバージョンは不明ですが、上手くいかなかった。

以下のコマンドでFlaskのバージョンを確認してみてください。

$ pip show flask
Name: Flask
Version: 1.0.3
Summary: A simple framework for building complex web applications.
//以下省略...

バージョンが1.0.xだった場合、上記のサイトではなくこちらのチュートリアルでやってみてください。

残念ながら英語です。頑張りましょう。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

エラー処理

https://www.kaggle.com/ldfreeman3/a-data-science-framework-to-achieve-99-accuracy
これを実行しすると

#pair plots of entire dataset
pp = sns.pairplot(data1, hue = 'Survived', palette = 'deep', size=1.2, diag_kind = 'kde', diag_kws=dict(shade=True), plot_kws=dict(s=10) )
pp.set(xticklabels=[])

上のコードで

LinAlgError singular matrix

というエラーが出た。
pp.set(xticklabels=[])を消すと動いた。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Pythonで画像認識して適切なファイル名を自動で付ける-Microsoft Computer Visionを利用

今回のプログラムはPythonで指定のフォルダに入った複数の画像ファイルを認識してファイル名を自動でつけるプログラムです。

画像認識にはMicrosoft Computer Visionを利用しています。

事前準備

Pythonで画像解析をするために、Microsoft Computer Vision APIのサブスクリプションキーの取得しておきます。

取得手順.

Microsoft Azureにアカウント登録⇒無料サブスクリプションで登録⇒Computer Vision APIを利用⇒キーを生成⇒取得

下記ページで登録、取得して下さい。
https://azure.microsoft.com/ja-jp/

下記ページのキー 1、2のどちらでも大丈夫です。
2019-06-22 14-17-29.jpg

プログラムのソースコード

# copyright symfony@lancers
# API reference :
# https://westus.dev.cognitive.microsoft.com/docs/services/5adf991815e1060e6355ad44/operations/56f91f2e778daf14a499e1fa
# 参考 : https://ledge.ai/microsoft-computer-vision-api/
# 機能概要 : img フォルダ中の画像をAI解析し、ファイルのリネームを行います。
# 使い方 : python3 cv_demo.py
# 注意 : サブスクリプションキーは変更してください

import requests
import glob
import os
import time

subscription_key = ""
assert subscription_key

vision_base_url = "https://westcentralus.api.cognitive.microsoft.com/vision/v2.0/"
analyze_url = vision_base_url + "analyze"


# ファイル名を変更
def file_rename(list_1, list_2):
    for i in range(len(list_1)):
        os.rename(list_1[i], './img/' + list_2[i] + '.jpg')


def ms_computer_vision_api(filepath):
    headers = {'Ocp-Apim-Subscription-Key': subscription_key,'Content-Type': 'application/octet-stream'}
    params = {'visualFeatures': 'Categories,Description,Color'}

    img = open(filepath, 'rb')
    img_byte = img.read()

    response = requests.post(analyze_url, data=img_byte, headers=headers, params=params)
    response.raise_for_status()

    return response.json()


if __name__ == "__main__":
    # 画像ファイルを配列に格納
    image_file = glob.glob('./img/*')

    vision_file_name = []

    start = time.time()

    # Computer Vision APIにリクエストして結果を取得
    for i in range(len(image_file)):
        json_data = ms_computer_vision_api(image_file[i])

        # 生成された文章を取得
        file_name = json_data['description']['captions'][0]['text']
        vision_file_name.append(file_name)

    # 文章の空白をファイル名用にアンダーバーに修正
    for i in range(len(vision_file_name)):
        vision_file_name[i] = vision_file_name[i].replace(' ', '_')

    file_rename(image_file,vision_file_name)

    # 経過時間を出力
    # print("elapsed_time:{0}".format(time.time() - start) + "[sec]")

上記 subscription_key = ""
のところに先ほどのキーの1または2のどちらかを入力しておきます。

カレントディレクトリに置いたimgファイルの中に解析したい画像を複数入れておきます。

結果

2019-06-22 14-27-40.jpg

上記のように画像解析してもともとあったタイトルを自動で適切な名前にリネームしてくれます。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Pythonでスクレイピング(BeautifulSoup)

python でスクレイピングをやったので、メモとして残しておきます。
(Pythonによるスクレイピング&機械学習を参考にやりました)

BeautifulSoup

BeautifulSoup : Pythonでスクレイピングをするのに欠かせない優秀なライブラリ。
HTMLやXMLを解析するライブラリです。

BeautifulSoup のインストール

$ pip3 install beautifulsoup4

pip3は、pipのpython3版です

Yahoo!ファイナンスの為替情報取得方法

sample.py
from bs4 import BeautifulSoup
import urllib.request as req

url = "https://stocks.finance.yahoo.co.jp/stocks/detail/?code=usdjpy"
res = req.urlopen(url)

soup = BeautifulSoup(res,"html.parser")

price = soup.select_one(".stoksPrice").string
print("usd/jpy",price)

POINT

HTMLを解析したいと思った時は、BeautifulSoupが便利みたいです!
構造が複雑でも、必要なデータ・欲しいデータを簡単に抽出できます。
また、CSSセレクタを利用した抽出にも対応しているので、Webブラウザーで構造を確認すれば、任意の要素を手軽に取り出せます。

参考文献

Pythonによるスクレイピング&機械学習

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

FLASK  ループでリストを出力【Windows.ver】

目標:ブラウザで下記を表示する
2019-06-22 (6).png

1.リストを作成する

sanrios=["キティちゃん", "シナモン", "マイメロ"]

2019-06-22 (4).png

return ところにsanrios=sanriosを追記
retuen render_template("index.html, name_value=name, sanrios=sanrios)

2.ループで出力する
{% for sanrio in sanrios: %}

{{ sanrio + "はピューロランドにでかけた" }}


2019-06-22 (3).png

{% endfor %}を忘れずに。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

3【*】Four Arithmetic by Machine Learning

積英語.png
Qiita民が大好きなPythonで積のパーセプトロンを作成しました。
I created a perceptron of multiplication in Python which Qiita people love.

# coding=utf-8
import numpy as np
import matplotlib.pyplot as plt

#Initial value
#number of learning
N = 500
#layer
layer = [2, 2, 1]
#bias
#bias = [0.0, 0.0]
#learning rate
η = [1.0, 1.0]
#number of middle layers
H = len(η) - 1
#teacher value
mul = [None for n in range(N)]
#Function output value
f_out = [[None for h in range(H + 1)] for n in range(N)]
#Function input value
f_in = [[None for h in range(H + 1)] for n in range(N)]
#weight
w = [[None for h in range(H + 1)] for n in range(N + 1)]
for h in range(H + 1):   
    w[0][h] = np.random.uniform(-1, 1, (layer[h], layer[h + 1]))
print(w[0])
#squared error
dE = [None for n in range(N)]
#∂E/∂IN
δ = [[None for h in range(H + 1)] for n in range(N)]

#Learning
for n in range(N):

    #Input value
    f_out[n][0] = np.random.uniform(-1, 1, (layer[0]))

    #teacher value
    mul[n] = f_out[n][0][0] * f_out[n][0][1]

    #order propagation
    f_in[n][0] = np.dot(f_out[n][0], w[n][0])
    f_out[n][1] = f_in[n][0] * f_in[n][0]
    #f_out[n][1] = np.array([f_in[n][0][0] * f_in[n][0][0], -f_in[n][0][1] * f_in[n][0][1]])

    #output value
    f_in[n][1] = np.dot(f_out[n][1], w[n][1])

    #squared error
    dE[n] = f_in[n][1] - mul[n]#value after squared error differentiation due to omission of calculation

    #back propagation
    δ[n][1] = 1.0 * dE[n]
    δ[n][0] = 2.0 * f_in[n][0] * np.dot(w[n][1], δ[n][1])
    #δ[n][0] = np.array([2.0 * f_in[n][0][0], -2.0 * f_in[n][0][1]]) * np.dot(w[n][1], δ[n][1])       
    for h in range(H + 1):
        w[n + 1][h] = np.array(w[n][h]) - η[h] * np.array([f_out[n][h][l] * δ[n][h] for l in range(layer[h])])

#Output
#Weight
print(w[N])
#Figure
#weight
#area height
py = np.amax(layer)
#area width
px = (H + 1) * 2
#area size
plt.figure(figsize = (16, 9))
#horizontal axis
x = np.arange(0, N + 1, 1)
#drawing
for h in range(H + 1):
    for l in range(layer[h]):
        #area matrix
        plt.subplot(py, px, px * l + h * 2 + 1)
        for m in range(layer[h + 1]):                       
            #line
            plt.plot(x, np.array([w[n][h][l, m] for n in range(N + 1)]), label = "w[" + str(h) + "][" + str(l) + "," + str(m) + "]")        
        #grid line
        plt.grid(True)
        #legend
        plt.legend(bbox_to_anchor = (1, 1), loc = 'upper left', borderaxespad = 0, fontsize = 10)

#save
plt.savefig('graph_mul.png') 
#show
plt.show()

重みの考え方を示します。 \\
I\ indicate\ the\ concept\ of\ weight. \\
 \\
w[0]=
\begin{pmatrix}
△ & □\\
▲ & ■
\end{pmatrix}
,w[1]=
\begin{pmatrix}
○ & ●
\end{pmatrix}\\
 \\
入力値とw[0]の積 \\
multiplication\ of\ input\ value\ and\ w[0]\\
w[0]
\begin{pmatrix}
a\\
b
\end{pmatrix}
=
\begin{pmatrix}
△ & □\\
▲ & ■
\end{pmatrix}
\begin{pmatrix}
a\\
b
\end{pmatrix}
=
\begin{pmatrix}
△a + □b\\
▲a + ■b
\end{pmatrix}\\
 \\
第1層に入力\\
enter\ in\ the\ first\ layer\\
\begin{pmatrix}
(△a + □b)^2\\
(▲a + ■b)^2
\end{pmatrix}\\
 \\
第1層出力とw[1]の積=出力値\\
product\ of\ first\ layer\ output\ and\ w[1]\ =\ output\ value\\
\begin{align}
&
w[1]
\begin{pmatrix}
(△a + □b)^2\\
(▲a + ■b)^2
\end{pmatrix}\\
=&
\begin{pmatrix}
○ & ●
\end{pmatrix}
\begin{pmatrix}
(a△ + b□)^2\\
(a▲ + b■)^2
\end{pmatrix}\\
=&〇(△a + □b)^2 + ●(▲a + ■b)^2\\
=&\quad (○△^2 + ●▲^2)a^2\\
&+(○□^2 + ●■^2)b^2\\\
&+(2〇△□+2●▲■)ab
\end{align}\\
 \\
なんだか、ややこしくなってしまってますが\\
とりあえずは、下記条件を満たせば積abを出力することができます。\\
It's\ getting\ confusing\\
For\ the\ moment,\ the\ multiplication\ ab\ can\ be\ output\ if\ the\ following\ conditions\ are\ satisfied.\\
\left\{
\begin{array}{l}
○△^2 + ●▲^2=0 \\
○□^2 + ●■^2=0 \\
2〇△□+2●▲■=1
\end{array}
\right.

毎度恒例、初期値を乱数(-1.0~1.0)の間で決めてから学習を繰り返すと目標値に収束するか試してみました。
Every time, after deciding the initial value between random numbers (-1.0~1.0),
I tried to repeat the learning to converge to the target value.

目標値\\
Target\ value\\
w[0]=
\begin{pmatrix}
△ & □\\
▲ & ■
\end{pmatrix}
,w[1]=
\begin{pmatrix}
○ & ●
\end{pmatrix}\\

\left\{
\begin{array}{l}
○△^2 + ●▲^2=0 \\
○□^2 + ●■^2=0 \\
2〇△□+2●▲■=1
\end{array}
\right.
\\
初期値\\
Initial\ value\\
w[0]=
\begin{pmatrix}
-0.06001642 & -0.85252436\\
-0.80560397 & 0.14216594
\end{pmatrix}
w[1]=
\begin{pmatrix}
-0.01316071\\
0.03798114
\end{pmatrix}\\
\left\{
\begin{array}{l}
○△^2 + ●▲^2=0.0246022702 \\
○□^2 + ●■^2=-0.0087975322 \\
2〇△□+2●▲■=-0.0100466654
\end{array}
\right.
\\
計算値\\
Calculated\ value\\
w[0]=
\begin{pmatrix}
-0.65548785 & -0.66341526\\
-0.62435684 & 0.63186139
\end{pmatrix}
w[1]=
\begin{pmatrix}
0.61080948\\
-0.59638741
\end{pmatrix}\\
\left\{
\begin{array}{l}
○△^2 + ●▲^2=0.0299584277 \\
○□^2 + ●■^2=0.0307223832 \\
2〇△□+2●▲■=1.0017919987
\end{array}
\right.

graph_mul.png

成功しましたが課題を抱えています。
It was successful but with challenges.

1,収束する時と収束しない時がある
1,There are cases when it converges and when it doesn't converge

初期値\\
Initial\ value\\
w[0]=
\begin{pmatrix}
0.96898039 & -0.13805777\\
0.5250381 & -0.457846
\end{pmatrix}
w[1]=
\begin{pmatrix}
0.17181768\\
0.27522847
\end{pmatrix}\\

計算値\\
Calculated\ value\\
w[0]=
\begin{pmatrix}
0.37373305 & -0.38455151\\
0.53163593 & -0.54773647
\end{pmatrix}
w[1]=
\begin{pmatrix}
0.34178043\\
0.33940928
\end{pmatrix}\\

graph_mul失敗.png

上記のように値が収束しない場合がときたまあります。
本当はプログラムを組んで収束しない時の統計を出すべきなんでしょうが
そこまでの気力がありませんでした。
Occasionally, the values don't converge as described above.
Properly, it should be put out the statistics when doesn't converge by programming
I didn't have the energy to get it.

2,収束したらしたでいつも同じぐらいの値で収束する
どういう訳か、例えばw[0][0,0]=±0.6...ぐらいの値に落ち着く事がほとんどです。
2,It always converges with the similar value
For some reason, for example, it is almost always settled to the value of w [0][0,0] = ±0.6...

一見、簡単そうなパーセプトロンでも謎が多いです。
At first glance, even the seemingly easy perceptron has many mystery.

NEXT
【/】

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

pythonでMecabを使いたい!

環境

ubuntu 16.04 LTS
python 3.7.3

やること

形態素解析の際に活躍するMecabですが、今回はpythonのプログラム内で、テキストを品詞ごとに分かち書きしたファイルを出力します。ただし、一般的なpython用のライブラリ(mecab-python3など)を使う方法ではなく、subprocessを介して外部のプログラムとして実行する方法でやってみます。以前、mecab-python3がどうしてもインストールできなかった時にこれを使っていました。同じような状況で困っている場合は参考にしてもらえればと思います。

Mecabをインストール

本体のインストール

$ sudo apt install mecab

辞書のインストール
今回はipadicを使います。他だとneologdがよく使われている印象です。

$ sudo apt install mecab-ipadic-utf8

一応これで使えるようになりますが、もうひとつインストールします。これがないと設定ファイルがどうのというエラーが出る場合があるそうです。

$ sudo apt install libmecab-dev

バージョンを確認

$ mecab --version
mecab of 0.996

お試しで形態素解析

$ echo "クリリンのことか… クリリンのことかーーーっ!!!" | mecab
クリ  名詞,一般,*,*,*,*,クリ,クリ,クリ
リン  名詞,一般,*,*,*,*,リン,リン,リン
の 助詞,連体化,*,*,*,*,の,ノ,ノ
こと  名詞,非自立,一般,*,*,*,こと,コト,コト
か 助詞,副助詞/並立助詞/終助詞,*,*,*,*,か,カ,カ
… 記号,一般,*,*,*,*,…,…,…
クリ  名詞,一般,*,*,*,*,クリ,クリ,クリ
リン  名詞,一般,*,*,*,*,リン,リン,リン
の 助詞,連体化,*,*,*,*,の,ノ,ノ
こと  名詞,非自立,一般,*,*,*,こと,コト,コト
か 助詞,副助詞/並立助詞/終助詞,*,*,*,*,か,カ,カ
ーーー   名詞,固有名詞,一般,*,*,*,*
っ 動詞,非自立,*,*,五段・カ行促音便,連用タ接続,く,ッ,ッ
! 記号,一般,*,*,*,*,!,!,!
! 記号,一般,*,*,*,*,!,!,!
! 記号,一般,*,*,*,*,!,!,!
EOS

python上で実行する

最初に述べたように、今回はテキストファイルから分かち書きしたファイルを出力します。

テキストデータ

jikaiyokoku.txt
やめて!ラーの翼神竜の特殊能力で、ギルフォード・ザ・ライトニングを焼き払われたら、
闇のゲームでモンスターと繋がってる城之内の精神まで燃え尽きちゃう!

お願い、死なないで城之内!あんたが今ここで倒れたら、舞さんや遊戯との約束はどうなっちゃうの? 
ライフはまだ残ってる。ここを耐えれば、マリクに勝てるんだから!

次回、「城之内死す」。デュエルスタンバイ!

コード

import subprocess

subprocess.call('mecab jikaiyokoku.txt -O wakati -o wakati.txt', shell=True)
# コマンドライン上で実行した場合と同じ結果にするため、shell=Tureというオプションをつける。

出力結果

wakati.txt
やめ て ! ラー の 翼 神 竜 の 特殊 能力 で 、 ギルフォード・ザ・ライトニング を 焼き払わ れ たら 、 
闇 の ゲーム で モンスター と 繋がっ てる 城之内 の 精神 まで 燃え尽き ちゃう ! 

お願い 、 死な ない で 城之内 ! あんた が 今 ここ で 倒れ たら 、 舞 さん や 遊戯 と の 約束 は どう なっ ちゃう の ? 
ライフ は まだ 残っ てる 。 ここ を 耐えれ ば 、 マリク に 勝てる ん だ から ! 

次回 、 「 城之内 死す 」 。 デュエルスタンバイ ! 

感想

Mecabがどうこうというよりsubprocessを紹介しただけみたいなところはあります!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

はじめてのプロコンメモ(その4)

はじめに

AtCoder に登録したら次にやること ~ これだけ解けば十分闘える!過去問精選 10 問 ~の類題もやっています
第 4 問(200 点)問題を解いています。

ABC 087 B - Coins

問題

あなたは、500円玉を A枚、100円玉を B枚、50円玉を C枚持っています。
これらの硬貨の中から何枚かを選び、合計金額をちょうど X円にする方法は何通りありますか。

同じ種類の硬貨どうしは区別できません。
2 通りの硬貨の選び方は、ある種類の硬貨についてその硬貨を選ぶ枚数が異なるとき区別されます。

標準入力

2
2
2
100
A = int(input())
B = int(input())
C = int(input())
X = int(input())
count = 0

for i in range(A+1):
  for t in range(B+1):
    for z in range(C+1):
      if X == 500*i + 100*t + 50*z:
        count = count + 1
print(count)

Cakes and Donuts

問題

ABC 洋菓子店では, 1個 4ドルのケーキと 1個 7ドルのドーナツが売られている.
このとき, 合計金額が Nドルとなる買い方はあるか, 判定せよ. ただし, 同じ商品を二個以上買っても良く, 買わない商品があっても良いものとする.

標準入力

11

作った解答

N = int(input())

count = 0

for i in range(100):
  for t in range(100):
    if N == 4*i + 7*t:
      count = count + 1

if count > 0:
  print("Yes")
else:
  print("No")

ARC 004 A - 2点間距離の最大値

問題

平面上に N個の点があり、それぞれ0からN−1までの番号が付けられており、それぞれの点について x座標と y座標が与えられています。その N点のうち 2点を選び結んで得られる線分のうち、最も長くなる線分の長さを求めてください。

標準入力

3
1 1
2 4
4 3

自分で作った解答

2次元配列を作るのにやたら手間取る

#平方根を求めるのでつかう
import math

#2次元配列は決まっているのでAに2次元配列をいれる
N = int(input())
A = [list(map(int, input().split())) for _ in range(N)]

largest_length = 0.0

for number in range(0,N):
  for number1 in range(0,N):
    x = A[number][0] - A[number1][0]
    y = A[number][1] - A[number1][1]
    length = math.sqrt(x*x + y*y)
    if largest_length < length:
      largest_length = length
print(largest_length)

参考資料

2次元配列をどうすれば入れられるのかわからなかったので下記リンクで解決した
https://qiita.com/naz_/items/9eed47f5483679fa66b1

http://kmjp.hatenablog.jp/entry/2013/04/06/1030

B - Sum of Three Integers

問題

2つの整数 K,Sが与えられます。
3つの変数 X,Y,Zがあり、0≦X,Y,Z≦Kを満たす整数の値を取ります。
X+Y+Z=Sを満たす X,Y,Zへの値の割り当ては何通りありますか。

入力例

2 2

解答

z = S - x - yの関係性に気づけなくて自力で解けなかったので解答をみた。
かなしい

K, S = map(int, input().split())

count = 0
for x in reversed(range(0,K+1)):
  for y in reversed(range(0,K+1)):
    z = S - x - y
    if z >= 0 and z <= K:
      print("x",x,"y",y,"z",z)
      count = count + 1

print(count)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Pythonでファイル名に現在時刻を付ける【初心者向け】

Pythonでログ出力ファイルを作成するときに、ファイル名に現在時刻を入れたときのメモです。
あわせて、csv出力に関するメモも記載しておきます。

現在日時の取得

datetime.datetime.now()で現在日時を取得できます。

print(datetime.datetime.now())

>>2019-06-22 09:44:54.569669

サンプル

ファイル名に現在時刻を入れて作成するサンプルです。
datetime.strftime()で日付フォーマット指定します。

 now = datetime.datetime.now()
 filename = './output/log_' + now.strftime('%Y%m%d_%H%M%S') + '.csv'
 f = open(filename, 'w')
 writer = csv.writer(f, lineterminator='\n') 

実行すると、log_20190622_094828.csvのようなファイル名で作成されます。

日付フォーマットの指定

ついでなので、C#でのDateTimeのフォーマット指定と比較します。

フォーマット pyhton C#
西暦(4桁) %Y yyyy
西暦(2桁) %y yy
月(2桁) %m MM
日(2桁) %d dd
時(2桁) %H HH
分(2桁) %M mm
秒(2桁) %S ss

月と分の大文字、小文字が逆なので、C#からPythonに移行する人はちょと注意が必要ですね。

csvファイル出力

writer.writerow(リスト配列)を使います。

#リスト配列はそのまま、指定する
a = [1,2,3]
writer.writerow(a)

>>1,2,3

#Numpy配列は、tolist()でリスト配列に変換してから
b = np.array([10, 20, 30])
writer.writerow(b.tolist())

>>10,20,30

#文字列などは、[]でリスト配列にしてから
writer.writerow(["日付",now])
writer.writerow(["日付",now.strftime('%Y/%m/%d'),now.strftime('%H:%M:%S')])

>>日付,2019-06-22 11:38:23.506582
>>日付,2019/06/22,11:38:23

datetime形式をそのまま出力したときは、エクセルで開いたときにキレイじゃないです。
(エクセルのバージョンにもよるかも知れないですが。)
csv日付.JPG

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

dict ってどう作るのが早いの?

あらすじ

テストとかで dict たくさん作るときあるけど、どっちのほうがきれいに書けるかなーっておもったので、
実際に計測してみた。(ひまじんか)
縦に書くか、横に書くか、さあどうなるか。。

実行環境

paiza.io にて python3 を指定

結果

方法1

import time
time_list = []
for times in range(100):
    start = time.time()
    a={}
    for i in range(10000):
        keys = [('customer{}'.format(i), '田中たろう'), ('phone_number{}'.format(i),'080-1111-2222'), ('order_number{}'.format(i), '0123456789')]
        tmp = dict(keys)
        a.update(tmp)
    elapsed_time = time.time() - start
    time_list.append(elapsed_time)
print(sum(time_list)/100)
# 0.015053222179412842

方法2

import time
time_list2 = []
for times in range(100):
    start = time.time()
    a = {}
    for i in range(10000):
        tmp = {}
        tmp['customer{}'.format(i)] = '田中たろう'
        tmp['phone_number{}'.format(i)] = '080-1111-2222'
        tmp['order_number{}'.format(i)] = '0123456789'
        a.update(tmp)
    elapsed_time = time.time() - start
    time_list2.append(elapsed_time)
print(sum(time_list2)/100)
# 0.011392412185668945

何回やってもかかる時間は 方法1 > 方法2 でした。

まとめ

方法2のほうが行数かかるけど見やすいし早いからいっか!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

GoogleColaboratoryで量子計算 - Strawberry Fieldsによる連続量光量子コンピュータ

下ブログで紹介した内容となります。
http://heppoko-souken.hatenablog.com/entry/2019/06/22/104500


連続量を用いた量子計算について

量子コンピュータというと最近興味を持つ方が増えてきていると思います。
その量子コンピュータですが、いくつかの種類がありまして、今回取り上げるのは光による量子コンピュータについてです。

光量子コンピュータは光(光子)を用いて量子計算を行う手法です。
日本では東大の古澤研究室で取り組まれていたりします。
専門外の方でも「量子テレーポーテーション」という言葉を聞いたことがあるかもしれません。
量子テレポーテーションも光による量子計算(量子情報)の分野と言えると思います。

光量子コンピュータの中でも離散量(Discrete-Variable)と連続量(Continuous-Variable)のどちらを用いるかで方式が異なるのですが、
特に連続量を用いた光量子コンピュータをここで扱っていきます。
私自身が大学で量子情報という分野で研究を行なっていたこともあり、個人的関心が強いため解説やらを書いていきたいと思っています。

GoogleColaboratoryでStrawberry Fieldsを実行する方法

連続量の光量子コンピュータのシミュレータとしてXANADU社によるオープンソース量子計算ソフトウェアStrawberry Fieldsがあります。
https://strawberryfields.readthedocs.io/en/latest/

今回はこのStrawberry Fieldsの導入を解説していきます。
実際に量子計算をしていくのは次回以降の予定です。(頑張って続き書きます。。。)

まずGoogleColaboratoryにログインしましょう。
そして次のコマンドでStrawberry Fieldsを実行する環境を導入します。

!pip install strawberryfields

これでStrawberry Fieldsの導入は完了です。
簡単でしたね。

次にStrawberry Fieldsのテストとして、1光子状態を生成して、その光子数を測定していきましょう。

import strawberryfields as sf
from strawberryfields.ops import *

eng, q = sf.Engine(1)

with eng:
    #1光子状態生成
    Fock(1)  | q[0]

    #光子数測定
    Measure  | q[0]

state = eng.run("fock", cutoff_dim=5)

print(Photon number : ", q[0].val)

これで動作すれば

Photon number : 1

という結果が得られるはずです。
1光子状態を生成し光子数を測定することで、光子が1個という測定結果を得られました。

簡単ではありましたがGoogleColaboratory上で光量子コンピュータのシミュレータであるStrawberry Fieldsを導入し、
コードを書き量子計算のシミュレーションを行うことができました。

実際の量子計算やStrawberry Fieldsの解説を次回以降書きたいと思っています。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

2019年版 リモートサーバでJupyter Notebookを実行する方法

GPU計算用に買ったWindowsマシンに、いつも使っているMacからリモートでJupyter Notebookを利用できるように設定をしたのでその覚え書きです。

設定方法についてはすでにたくさんの記事が書かれていますが、今はもっと簡単にできるようになっています。

前提条件

  • ローカルのネットワーク内で利用
  • サーバのOSはWindows 10
  • ユーザーは1人

複数ユーザーの場合はJupyterHubを使うようにとドキュメントに書かれています。
Running a notebook server — Jupyter Notebook 5.7.8 documentation

サーバ側の作業

1. パスワードの設定

jupyter notebook passwordを実行するとパスワードを聞かれるので、設定したいパスワードを入力します。

> jupyter notebook password
Enter password:
Verify password:
[NotebookPasswordApp] Wrote hashed password to C:\Users\masahiro\.jupyter\jupyter_notebook_config.json

パスワードを入力すると、パスワードから生成されたハッシュ値が自動的にファイルに保存されます。

jupyter_notebook_config.json
{
  "NotebookApp": {
    "password": "sha1:67c9e60bb8b6:9ffede0825894254b2e042ea597d771089e11aed"
  }
}

Automatic Password setup — Jupyter Notebook 5.7.8 documentation

2. ファイアウォールの設定

Jupyter Notebookが使うポートの通信を許可する設定を行います。
デフォルトでは8888ポートを使うようになっているので、下のページの手順にしたがって8888ポートの通信を許可します。

Windows10で特定のポートを開放する – Born Digital サポート

3. Jupyter Notebookの起動

Jupyter Notebookを外部から接続できるように--ipオプションで接続元のIPアドレスを指定して起動します。--ip=*とするとどこからでも接続できるようになります。
サーバ側ではブラウザを開く必要がないので--no-browserオプションをつけて起動します。

> jupyter notebook --ip=* --no-browser

クライアント側の作業

ブラウザを起動して、下のURLにアクセスします。
http://[IPアドレス]:8888

MacからWindowsに接続する場合はホスト名+.localで指定することもできます。
http://[ホスト名].local:8888

接続するとパスワードを聞かれるので、設定したパスワードを入力します。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

出力引数はいずこへ...

背景と経緯

どうやら僕の頭の中には査読者が住んでおられるようです(※1).これは性分としか言いようがないのですが,なにがしかの文章を書いているときはほとんどかならず査読チェックが入ります.
つい今しがたも,初学者用の資料に「関数から返ってくる値のことを”出力引数”または”戻り値”という...」なんてことを何の気なしに書こうとしてしまったので,査読者から「それってほんとに同じものなの?中途半端な自分の知識だけで書こうとしてない?馬鹿なの?死ぬの?」というご指摘を受けてしまいました.もうしわけありません.

さっそく「出力引数」と「戻り値」という二つのキーワードでググってみると,「“引数”とは関数に渡す値(=私が入力引数と認識しているもの)で,“戻り値”は関数から戻ってくる値」という説明が多いように思います.たとえば,こちらのサイト

はて,私がプログラミングをかじり始めたのはかれこれ20年も前ですが(かじり続けて20年),そのときには「出力引数」とか「入力引数」とかって言ってた気がするんだけど,あれは幻だったのかしらん...自分の記憶に一抹の不安(唐松の文様,十四松の寝袋)を覚えたので,改めて「"出力引数"」で調べてみました(結果).

なんだ,あるではないか.引っかかってきたのは,MATLABやらScilabやらFortranやらの公式っぽいドキュメントですね.「出力引数」という日本語が存在していることは確認できましたが,「出力引数」と「戻り値」の関係はさっぱりわからん.というわけで,私なりに調べてみました.

まとめ

書いているとわりと長くなってしまったので,最初にまとめておくと以下のようになります.
出力引数と戻り値はおなじというのが現時点の結論です,しかし,引数には入力・出力とかの区別があったり,仮引数・実引数とかの区別があったりして,出力引数や戻り値たちの立ち位置はちょっとあいまいです.英語のほうは,入出力および仮・実の区別がはっきりとしていて,2つの軸に沿って言葉が使い分けられてわりとわかりやすいのです(以下参照).
image.png

一方,日本語は入出力および仮・実の区別を同時に行っていないようなので,曖昧さがうまれているように思います.とりあえず,ワタシの理解を,英語における区別と対応させて表にしました.
image.png
ここで,実引数および戻り値を「入力引数」と「出力引数」にそれぞれ対応させたのは,MATLABドキュメンテーションで,input arugumentの対訳が入力引数,output argumentの対訳が出力引数になっているのを参考にしました.

そもそも,日本語で「引数」とした場合には「仮引数」なのか「実引数」なのかわかんないので,もういっそのこと
image.png
ってしちゃえばいいんじゃない?

めんどくさいですね...すみません.

しらべてみたよ

といっても,googleとwikipediaをあたってみただけなのですが.

最初の手がかりにしたのはMATLABのドキュメンテーション.なぜMATLABかっていうと,僕が日常的によく使っているってのと,ドキュメンテーションがしっかりしている(商用なので無責任なことは書きますまい)という期待からです.んで,そのドキュメンテーションには「出力引数」の英訳として「output argument」っていうんがあるわけです.たとえば,こちら(日本語)こちら(英語)を比較.

んで,google検索して引っかかってきたwikipediaのページが"Parameter (computer programming)"というページです.Wikipediaのサイト内検索で"output argument"を探しても,トップに出てくるのはこのページ.英語でも"output argument"は駆逐されてしまったのかと不安になりながら,件のページで"outpt argument"に関する記述をさがすと...ありました.
image.png

うーん.いまいちピンとこないです."output argument"と対になる"input argument"の記述を見てみると,

An input argument (the argument to an input parameter)

とあります.ということは,アナロジーを駆使すると,

An output argument = the argument to an output parameter

と類推できますね.

じゃあ,argumentとparameterの違いってなんやねんということになりますが,同じページに書いてありました.
image.png

なんだか,英語のほうがスッキリ区別できるような気がします.上記の記事によると,
・parameter (formal argument) = "variable"
・argument (actual argument or actural parameter) = "value"
ということらしいです.paramterは特定の値がassign(=代入)される(されうる)「入れ物」,argumentはassignされる値そのものという理解です.

こうして理解すると,少なくとも英語には"value or not"と"in or out"という2つの軸がありそうです.表にするとこんな感じ.
image.png

スッキリ.

いやいや,僕が知りたかったのは日本語の「出力引数」なのでもうちょっとがんばります.上記の「parameterとargumentの違い」は日本語の「仮引数と実引数の違い」に対応しそうです.こちらでは仮引数と実引数の違いが解説されています.仮引数が"parameter"に対応し,実引数が"argument"に対応するようです.このように英語と日本語の対応を考えると,かねてからの懸案であった「出力引数」は,英語の"output argument"の対訳としてまったく問題がなさそうです.

そして,「戻り値」のほうですが,こちらでは,「関数が渡す値」となっております."output argument(出力引数)"が意味するものと同じと考えてよさそうです.

つまり,「出力引数」=「戻り値」

よかったよかった.おかえりなさい,出力引数.
これでワタシのなかの査読者にも納得してもらえる.
僕の記憶もあながち捨てたもんじゃなかったのね...

あれ???

さきほどのページでは,「引数」という言葉は「関数に渡される」という意味で解説されています.関数から戻ってくるものへの言及は避けられています.冒頭で紹介したページも同様です.じゃあ,"output parameter"に対応する日本語ってどうなってんのでしょうか?

私の頭の中をまとめるとこんなかんじ.
image.png

どうしよう.どなたかご存知でしたら教えてください.

さいごに

「出力引数」問題についてはワタシの頭の中の査読者をなんとか納得させることができました.でも,朝の貴重な原稿書きの時間の全てをこの記事に費やしてしまったために,ワタシの頭の中の指導教官に「進捗はどうした?」と詰められています.

生きづらい...

脚注

※1)しょせんワタシの中の査読者なので諸々の指摘抜けが発生します.この投稿に不正確な部分があっても怒らないでくdさい.やさしく教えて.

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

pyenv3.7系での環境構築にひたすら躓いた話

pyenvを用いた、Python 3.7.2の環境構築にひたすら躓いたので、解決手順をまとめていきます。

環境はUbuntu16.04、Google Cloud Computing Engineを利用しています。

1. no acceptable C compiler found

$ pyenv install 3.7.2
Downloading Python-3.7.2.tar.xz...
-> https://www.python.org/ftp/python/3.7.2/Python-3.7.2.tar.xz
Installing Python-3.7.2...

BUILD FAILED (Ubuntu 16.04 using python-build 1.2.12-2-geb68ec9)

Inspect or clean up the working tree at /tmp/python-build.20190621225531.4895
Results logged to /tmp/python-build.20190621225531.4895.log

Last 10 log lines:
checking for --enable-universalsdk... no
checking for --with-universal-archs... no
checking MACHDEP... checking for --without-gcc... no
checking for --with-icc... no
checking for gcc... no
checking for cc... no
checking for cl.exe... no
configure: error: in `/tmp/python-build.20190621225531.4895/Python-3.7.2':
configure: error: no acceptable C compiler found in $PATH
See `config.log' for more details

gccをインストールすることで解決。

$ sudo apt-get install buid-essential

2. ZipImportError

$ pyenv install 3.7.2
Downloading Python-3.7.2.tar.xz...
-> https://www.python.org/ftp/python/3.7.2/Python-3.7.2.tar.xz
Installing Python-3.7.2...

BUILD FAILED (Ubuntu 16.04 using python-build 1.2.12-2-geb68ec9)

Inspect or clean up the working tree at /tmp/python-build.20190621230110.10841
Results logged to /tmp/python-build.20190621230110.10841.log

Last 10 log lines:
    sys.exit(ensurepip._main())
  File "/tmp/python-build.20190621230110.10841/Python-3.7.2/Lib/ensurepip/__init__.py", line 204, in _main
    default_pip=args.default_pip,
  File "/tmp/python-build.20190621230110.10841/Python-3.7.2/Lib/ensurepip/__init__.py", line 117, in _bootstrap
    return _run_pip(args + [p[0] for p in _PROJECTS], additional_paths)
  File "/tmp/python-build.20190621230110.10841/Python-3.7.2/Lib/ensurepip/__init__.py", line 27, in _run_pip
    import pip._internal
zipimport.ZipImportError: can't decompress data; zlib not available
Makefile:1130: recipe for target 'install' failed
make: *** [install] Error 1

Zlibが無いということでインストールして解決。

$ sudo apt-get install zlib1g-dev

3. ModuleNotFoundError: No module named '_ctypes'

$ pyenv install 3.7.2
Downloading Python-3.7.2.tar.xz...
-> https://www.python.org/ftp/python/3.7.2/Python-3.7.2.tar.xz
Installing Python-3.7.2...

BUILD FAILED (Ubuntu 16.04 using python-build 1.2.12-2-geb68ec9)

Inspect or clean up the working tree at /tmp/python-build.20190621230630.24266
Results logged to /tmp/python-build.20190621230630.24266.log

Last 10 log lines:
  File "/tmp/tmp9dawx9je/pip-18.1-py2.py3-none-any.whl/pip/_internal/commands/__init__.py", line 6, in <module>
  File "/tmp/tmp9dawx9je/pip-18.1-py2.py3-none-any.whl/pip/_internal/commands/completion.py", line 6, in <module>
  File "/tmp/tmp9dawx9je/pip-18.1-py2.py3-none-any.whl/pip/_internal/cli/base_command.py", line 18, in <module>
  File "/tmp/tmp9dawx9je/pip-18.1-py2.py3-none-any.whl/pip/_internal/download.py", line 38, in <module>
  File "/tmp/tmp9dawx9je/pip-18.1-py2.py3-none-any.whl/pip/_internal/utils/glibc.py", line 3, in <module>
  File "/tmp/python-build.20190621230630.24266/Python-3.7.2/Lib/ctypes/__init__.py", line 7, in <module>
    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-get install libffi-dev

4. Missing the bzip2 lib? Missing the bzip2 lib? OpenSSL lib?

$ pyenv install 3.7.2
Downloading Python-3.7.2.tar.xz...
-> https://www.python.org/ftp/python/3.7.2/Python-3.7.2.tar.xz
Installing Python-3.7.2...
WARNING: The Python bz2 extension was not compiled. Missing the bzip2 lib?
WARNING: The Python readline extension was not compiled. Missing the GNU readline lib?
ERROR: The Python ssl extension was not compiled. Missing the OpenSSL lib?

Please consult to the Wiki page to fix the problem.
https://github.com/pyenv/pyenv/wiki/Common-build-problems


BUILD FAILED (Ubuntu 16.04 using python-build 1.2.12-2-geb68ec9)

Inspect or clean up the working tree at /tmp/python-build.20190621231127.5162
Results logged to /tmp/python-build.20190621231127.5162.log

Last 10 log lines:
        install|*) ensurepip="" ;; \
    esac; \
     ./python -E -m ensurepip \
        $ensurepip --root=/ ; \
fi
Looking in links: /tmp/tmpid_vpfsb
Collecting setuptools
Collecting pip
Installing collected packages: setuptools, pip
Successfully installed pip-18.1 setuptools-40.6.2

https://github.com/pyenv/pyenv/wiki/Common-build-problems を見ろとのことなので、こちらに記載のある以下のコマンドにて解決。

$ sudo apt-get install -y make build-essential libssl-dev zlib1g-dev libbz2-dev \
libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev libncursesw5-dev \
xz-utils tk-dev libffi-dev liblzma-dev python-openssl git
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Ubuntu16.04でpyenv3.7系の環境構築にひたすら躓いた話

pyenvを用いた、Python3.7.2の環境構築にひたすら躓いたので、解決手順をまとめていきます。

環境はUbuntu16.04、Google Cloud Computing Engineを利用しています。

1. no acceptable C compiler found

$ pyenv install 3.7.2
Downloading Python-3.7.2.tar.xz...
-> https://www.python.org/ftp/python/3.7.2/Python-3.7.2.tar.xz
Installing Python-3.7.2...

BUILD FAILED (Ubuntu 16.04 using python-build 1.2.12-2-geb68ec9)

Inspect or clean up the working tree at /tmp/python-build.20190621225531.4895
Results logged to /tmp/python-build.20190621225531.4895.log

Last 10 log lines:
checking for --enable-universalsdk... no
checking for --with-universal-archs... no
checking MACHDEP... checking for --without-gcc... no
checking for --with-icc... no
checking for gcc... no
checking for cc... no
checking for cl.exe... no
configure: error: in `/tmp/python-build.20190621225531.4895/Python-3.7.2':
configure: error: no acceptable C compiler found in $PATH
See `config.log' for more details

gccをインストールすることで解決。

$ sudo apt-get install buid-essential

2. ZipImportError

$ pyenv install 3.7.2
Downloading Python-3.7.2.tar.xz...
-> https://www.python.org/ftp/python/3.7.2/Python-3.7.2.tar.xz
Installing Python-3.7.2...

BUILD FAILED (Ubuntu 16.04 using python-build 1.2.12-2-geb68ec9)

Inspect or clean up the working tree at /tmp/python-build.20190621230110.10841
Results logged to /tmp/python-build.20190621230110.10841.log

Last 10 log lines:
    sys.exit(ensurepip._main())
  File "/tmp/python-build.20190621230110.10841/Python-3.7.2/Lib/ensurepip/__init__.py", line 204, in _main
    default_pip=args.default_pip,
  File "/tmp/python-build.20190621230110.10841/Python-3.7.2/Lib/ensurepip/__init__.py", line 117, in _bootstrap
    return _run_pip(args + [p[0] for p in _PROJECTS], additional_paths)
  File "/tmp/python-build.20190621230110.10841/Python-3.7.2/Lib/ensurepip/__init__.py", line 27, in _run_pip
    import pip._internal
zipimport.ZipImportError: can't decompress data; zlib not available
Makefile:1130: recipe for target 'install' failed
make: *** [install] Error 1

Zlibが無いということでインストールして解決。

$ sudo apt-get install zlib1g-dev

3. ModuleNotFoundError: No module named '_ctypes'

$ pyenv install 3.7.2
Downloading Python-3.7.2.tar.xz...
-> https://www.python.org/ftp/python/3.7.2/Python-3.7.2.tar.xz
Installing Python-3.7.2...

BUILD FAILED (Ubuntu 16.04 using python-build 1.2.12-2-geb68ec9)

Inspect or clean up the working tree at /tmp/python-build.20190621230630.24266
Results logged to /tmp/python-build.20190621230630.24266.log

Last 10 log lines:
  File "/tmp/tmp9dawx9je/pip-18.1-py2.py3-none-any.whl/pip/_internal/commands/__init__.py", line 6, in <module>
  File "/tmp/tmp9dawx9je/pip-18.1-py2.py3-none-any.whl/pip/_internal/commands/completion.py", line 6, in <module>
  File "/tmp/tmp9dawx9je/pip-18.1-py2.py3-none-any.whl/pip/_internal/cli/base_command.py", line 18, in <module>
  File "/tmp/tmp9dawx9je/pip-18.1-py2.py3-none-any.whl/pip/_internal/download.py", line 38, in <module>
  File "/tmp/tmp9dawx9je/pip-18.1-py2.py3-none-any.whl/pip/_internal/utils/glibc.py", line 3, in <module>
  File "/tmp/python-build.20190621230630.24266/Python-3.7.2/Lib/ctypes/__init__.py", line 7, in <module>
    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-get install libffi-dev

4. Missing the bzip2 lib? Missing the bzip2 lib? OpenSSL lib?

$ pyenv install 3.7.2
Downloading Python-3.7.2.tar.xz...
-> https://www.python.org/ftp/python/3.7.2/Python-3.7.2.tar.xz
Installing Python-3.7.2...
WARNING: The Python bz2 extension was not compiled. Missing the bzip2 lib?
WARNING: The Python readline extension was not compiled. Missing the GNU readline lib?
ERROR: The Python ssl extension was not compiled. Missing the OpenSSL lib?

Please consult to the Wiki page to fix the problem.
https://github.com/pyenv/pyenv/wiki/Common-build-problems


BUILD FAILED (Ubuntu 16.04 using python-build 1.2.12-2-geb68ec9)

Inspect or clean up the working tree at /tmp/python-build.20190621231127.5162
Results logged to /tmp/python-build.20190621231127.5162.log

Last 10 log lines:
        install|*) ensurepip="" ;; \
    esac; \
     ./python -E -m ensurepip \
        $ensurepip --root=/ ; \
fi
Looking in links: /tmp/tmpid_vpfsb
Collecting setuptools
Collecting pip
Installing collected packages: setuptools, pip
Successfully installed pip-18.1 setuptools-40.6.2

https://github.com/pyenv/pyenv/wiki/Common-build-problems を見ろとのことなので、こちらに記載のある以下のコマンドにて解決。

$ sudo apt-get install -y make build-essential libssl-dev zlib1g-dev libbz2-dev \
libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev libncursesw5-dev \
xz-utils tk-dev libffi-dev liblzma-dev python-openssl git
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

flaskアプリを、pdbを活用してデバッグする

手順

stack overflowのDebugging flask with pdbを参考にしています。

  1. screenなどを使って2つ端末を立ち上げておきます。以降端末1、端末2と書きます。

  2. flaskアプリ上のデバッグを開始したい箇所に、次のコードを埋め込みます。

    import pdb; pdb.set_trace()
    
  3. 端末1で、flaskのdevelopment用サーバをflask runにて起動します。下のようにFLASK_ENVを設定するとデバッグ出力モードになります。(参考:flask Development Server

    $ export FLASK_ENV=development
    $ flask run
    
  4. この状態のまま、端末2で、curlコマンドで該当のアプリにアクセスします。
    なお、curlの使い方は「curlコマンドの使い方 ~GET、POST、REST(json)の確認と、windowsでの利用手順」が分かりやすく参考になりました。

  5. そうすると、端末2(curl側)では待機状態になっているはずです。このまま端末1(flask側)を見るとpdbに入っていますので、後は端末1側でpdbにてデバッグすることができます。

環境

次でできました。難しい仕組みを使っていないので、広く活用できると思います。
flask: 1.0.2
python: 3.7.3
サーバ側のOS: linux(CentOS7)

最後に

pdbはシンプルで便利なので、flaskアプリでもpdbでデバッグができて幸せでした。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む