- 投稿日:2019-06-22T23:35:59+09:00
Excelで1セル内に複数の書式(フォント)が混在するようなものをPythonで扱いたい
この記事の対象
タイトルにある「1セル内に複数の書式が混在するようなもの」とは、下図スクリーンショットのA2セルのようなものを想定しています。
そして、本記事でやりたいことは、以下の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ファイルが出力されます。
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引数以降が、設定したい文字列や書式になります。
- 投稿日:2019-06-22T22:57:09+09:00
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]) # 10ctypesで扱える型の一覧
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
- 投稿日:2019-06-22T22:44:58+09:00
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])
- 投稿日:2019-06-22T20:10:55+09:00
FLASK キャラクターの行動メニューを表示する【Windows.ver】
目標:共通テンプレートを使って、ブラウザで下記のようにキティの行動が表示されるようにする
共通テンプレートの作り方はこちらの記事☞FLASK 共通テンプレートの作り方【Windows.ver】
1.行動の指示をだすためのファイルを作成
●新規ファィルを作成 ファイル名:Character_menu.py
●下記のようにコードを書く
2.新規でhtmlのファィルを作成
共通テンプレートのファィルlayout.htmlはすでに作成してあるので、それをextendsで引っ張ってくる
行動をhtmlの中に記述。しかし、リンクを押すとエラーになります!
なぜならリンク先を指定していないから。action.htmlという新しいファィルを作成する
これはmenu.htmlをコピーして
コードを編集するとよい
- 投稿日:2019-06-22T19:31:13+09:00
Tornado(websocket)とVueを使ってTwitterのトレンドを表示する
出来上がったもの
Tornadoについて
公式ドキュメント
Facebookにより開発されているPythonで書かれたWebフレームワーク。
ノンブロッキングI/Oを使用しているので、WebSocketなど長期接続を必要とするアプリケーションに最適だとドキュメントで紹介されています。アプリケーションの概要
TwitterApiでトレンドを一定間隔で取得 → websocketでクライアントにプッシュ → Vue.jsでリストレンダリング
という単純なものです。
サーバーサイド
公式のwebsocketデモアプリを少し改変した程度です。
トレンドを一定間隔で取得する
app.pyapi = 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.pyclass 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.pyif 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.environHEROKUを使うにあたって
.env
ファイルで環境変数を切り替えています。
また、こちらのプラグインを使うとheroku config:push
コマンドでローカルの.env
ファイルの内容をHEROKUの環境変数に設定できるのでおすすめです。クライアントサイド
単純なアプリなのでvue-cliを使わずCDNを使っています。
その際、注意すべき点として記法の衝突があります。
Tornadoのテンプレートで使う{{}}
がVueのマスタッシュ記法と同じになってしまいエラーが発生します。app.jsconst 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
タグを使い、tag
にtbody
を指定したのですが動作しませんでした。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>こうすることでうまく動作しました。
- 投稿日:2019-06-22T18:53:16+09:00
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>対象ドライバー
- ChromeDriver (google chrome)
- geckodriver (firefox)
find_elementの引数
- DevToolsから得られたXPath
- 簡潔なXPath
- 冗長なXPath
- クラス名
- Name属性
- 簡潔なCSSセレクタ
- 冗長なCSSセレクタ
ソース
pythonimport 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.159016132354736geckodriver
実行結果の抜粋
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倍ほど速くなりました。(*´ω`*)
- 投稿日:2019-06-22T18:48:30+09:00
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日あるみたいです。
最後に
大晦日が素数日ってなんかエモいやん?
- 投稿日:2019-06-22T18:29:07+09:00
【Python】Dashのcallbackにアニメーションをつける
Dash Loading Component
背景
Dashの可視化アプリケーションの描画に、loadingアニメーションをつけたいと思いました.
ちなみに、デフォルトだと以下のように何も変化がなく、inputを検知したことが伝わりにくくなってしまいます.
環境
- 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.pyimport 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)結果
その他
spinnerの種類は上のdefaultを含めて5種類用意されているようです.
- graph
- cube
- circle
- dot
ぜひお試しください!
参考
- 投稿日:2019-06-22T18:13:55+09:00
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を使ったほうが良さそうです。
- 投稿日:2019-06-22T17:27:22+09:00
プログラミング完全初心者がChainerでディープラーニングを学んでみた
環境
この記事では、Python3.6以上であることが前提です。
実行はGoogle Colaboratory というサービスを利用し、ブラウザ上で実行しています。
Chainerページ: 1.はじめに-ディープラーニング入門学んだこと
はじめは
型(type)
の説明があり、次に算術演算子(+,-,*,/)
を学びました。
メゾット(method)
やformat()
、list tuple dictionary
などもありました。
僕みたいな完全な初心者にもわかるように、一つ一つ丁寧に説明があり、とてもすすめやすかったです。
他にもif文
やfor文
などpythonのほぼすべてを学ぶことができるので、プログラミングが全くわからない状態でディープラーニングをやってみたいというかたにおすすめです。
- 投稿日:2019-06-22T17:09:04+09:00
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)とりあえず動かすのだ ファファファファ
大元の文章
色々こねくり回して、指定の単語を含む文章を取得
上記はわかりやすくするため、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/
- 投稿日:2019-06-22T16:52:37+09:00
MiniPC ✕ DL ✕ Drone
この記事は、2019年07月13日(土) に名古屋駅至近で開催の「ディープラーニングガジェット品評会」の発表用資料です。
ディープラーニングガジェット品評会
https://connpass.com/event/129065/
1.はじめに
1−1.PINTO何者?
- Tensorflow の ビルドジャンキー
- Intel Software Innovator
- COBOLer
https://qiita.com/PINTO
https://github.com/PINTO0309
1−2.本日のネタ
- 小型PC (GPUなし)
- ドローン
- ディープラーニング (Pose Estimation)
↓で、
爆速ガジェットを組みたい
GPU つかわない
ココが飛び出てるのがヤダ
↓
発売直後に購入してまだ電源1度も入れていない
2.構成
2−1.小型PC
GPD Pocket 2 (超高価)
良い子はぜったいマネして買わないように
スペック スペック スペック 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.ドローン
- Pythonで動かせる
- 安価
- 安全
- おもちゃ
2−3.ディープラーニング
Pose Estimation (MobileNetV2)
- 軽量 (2 MB 〜 9 MB)
- 速い (10 FPS 〜 30 FPS)
- 精度ボチボチ
3.MobileNetV2 based Pose Estimation 動画デモ
3−1.OpenVINOあり + CPU推論
PoseEstimation + MobileNetV2, OpenVINO, 30 FPS++, Qiita埋め込み用https://t.co/Fp8RNqAmQ0
— PINTO0309 (@PINTO03091) June 22, 20193−2.OpenVINOなし + GPU (NVIDIA GTX 1070) 推論
PoseEstimation + MobileNetV2, OpenVINOなし+NVIDIA GPU, 30 FPS++, Qiita埋め込み用https://t.co/quPjJlZM03
— PINTO0309 (@PINTO03091) June 23, 2019
4.OpenVINO
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.本日のガジェット
Drone + MovileNetV2 Pose Estimation + CPU only + OpenVINO, Qiita投稿用https://t.co/AKQhUHSYz0
— PINTO0309 (@PINTO03091) July 12, 2019
9.ハマったこと
- Flask 分からん!!
- Drone が10分ぐらいでオーバーヒートしてしまう
- Wi-Fiがたまに不安定
- ジェスチャーの判定がとても難しい
- マウス壊れた
- 酷使しすぎてキーボードの E と M と - が壊れた
10.本当は。。。
- ラズパイ + Edge TPU Accelerator で爆速ガジェットが作りたかった
- ResNet-50で性能改善を図りたい
- 3D-PoseEstimation にチャレンジしたい
- ジェスチャーでDrone操作できるようにしたい
11.さいごに
本日のガジェットは @Kodamapさん の協力を得て作成されています。 というか、ほぼ @Kodamapさんの功績です。
とても助かりました! ありがとうございます!
https://qiita.com/kodamap
https://github.com/kodamap
ご清聴有難うございました。
コレ欲しい。。。 ラズパイZeroクラスタ化ハット
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
- 投稿日:2019-06-22T16:12:11+09:00
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]
- 投稿日:2019-06-22T16:06:00+09:00
FLASK 共通テンプレートの作り方【Windows.ver】
共通テンプレートの作り方
- templetes フォルダにindex.htmlの内容をコピーして新しいファイルlayout.htmlを作成
このコードを編集してlayout.htmlに共通テンプレートを作っていきましょう!
<body></body>の中に
<P>共通テンプレート</p>
{% block content %}
{% endblock %}<head><head/>のヘッダーの中身を削除
{% extends "layout.html" %}で共通テンプレートのlayout.htmlをよびだす
{% block content %}と記載。これより先のコードを
layout.htmlの{% block content %}の部分に埋め込むイメージコードの末は
{% endblock %}ブラウザで表示すると
- 投稿日:2019-06-22T15:32:11+09:00
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だった場合、上記のサイトではなくこちらのチュートリアルでやってみてください。
残念ながら英語です。頑張りましょう。
- 投稿日:2019-06-22T14:42:04+09:00
エラー処理
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=[])を消すと動いた。
- 投稿日:2019-06-22T14:29:02+09:00
Pythonで画像認識して適切なファイル名を自動で付ける-Microsoft Computer Visionを利用
今回のプログラムはPythonで指定のフォルダに入った複数の画像ファイルを認識してファイル名を自動でつけるプログラムです。
画像認識にはMicrosoft Computer Visionを利用しています。
事前準備
Pythonで画像解析をするために、Microsoft Computer Vision APIのサブスクリプションキーの取得しておきます。
取得手順.
Microsoft Azureにアカウント登録⇒無料サブスクリプションで登録⇒Computer Vision APIを利用⇒キーを生成⇒取得
下記ページで登録、取得して下さい。
https://azure.microsoft.com/ja-jp/プログラムのソースコード
# 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-22T14:21:10+09:00
Pythonでスクレイピング(BeautifulSoup)
python でスクレイピングをやったので、メモとして残しておきます。
(Pythonによるスクレイピング&機械学習を参考にやりました)BeautifulSoup
BeautifulSoup : Pythonでスクレイピングをするのに欠かせない優秀なライブラリ。
HTMLやXMLを解析するライブラリです。BeautifulSoup のインストール
$ pip3 install beautifulsoup4pip3は、pipのpython3版です
Yahoo!ファイナンスの為替情報取得方法
sample.pyfrom 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ブラウザーで構造を確認すれば、任意の要素を手軽に取り出せます。参考文献
- 投稿日:2019-06-22T13:51:39+09:00
FLASK ループでリストを出力【Windows.ver】
- 投稿日:2019-06-22T13:06:56+09:00
3【*】Four Arithmetic by Machine Learning
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.成功しましたが課題を抱えています。
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}\\上記のように値が収束しない場合がときたまあります。
本当はプログラムを組んで収束しない時の統計を出すべきなんでしょうが
そこまでの気力がありませんでした。
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
【/】
- 投稿日:2019-06-22T12:18:00+09:00
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 クリ 名詞,一般,*,*,*,*,クリ,クリ,クリ リン 名詞,一般,*,*,*,*,リン,リン,リン の 助詞,連体化,*,*,*,*,の,ノ,ノ こと 名詞,非自立,一般,*,*,*,こと,コト,コト か 助詞,副助詞/並立助詞/終助詞,*,*,*,*,か,カ,カ … 記号,一般,*,*,*,*,…,…,… クリ 名詞,一般,*,*,*,*,クリ,クリ,クリ リン 名詞,一般,*,*,*,*,リン,リン,リン の 助詞,連体化,*,*,*,*,の,ノ,ノ こと 名詞,非自立,一般,*,*,*,こと,コト,コト か 助詞,副助詞/並立助詞/終助詞,*,*,*,*,か,カ,カ ーーー 名詞,固有名詞,一般,*,*,*,* っ 動詞,非自立,*,*,五段・カ行促音便,連用タ接続,く,ッ,ッ ! 記号,一般,*,*,*,*,!,!,! ! 記号,一般,*,*,*,*,!,!,! ! 記号,一般,*,*,*,*,!,!,! EOSpython上で実行する
最初に述べたように、今回はテキストファイルから分かち書きしたファイルを出力します。
テキストデータ
jikaiyokoku.txtやめて!ラーの翼神竜の特殊能力で、ギルフォード・ザ・ライトニングを焼き払われたら、 闇のゲームでモンスターと繋がってる城之内の精神まで燃え尽きちゃう! お願い、死なないで城之内!あんたが今ここで倒れたら、舞さんや遊戯との約束はどうなっちゃうの? ライフはまだ残ってる。ここを耐えれば、マリクに勝てるんだから! 次回、「城之内死す」。デュエルスタンバイ!コード
import subprocess subprocess.call('mecab jikaiyokoku.txt -O wakati -o wakati.txt', shell=True) # コマンドライン上で実行した場合と同じ結果にするため、shell=Tureというオプションをつける。出力結果
wakati.txtやめ て ! ラー の 翼 神 竜 の 特殊 能力 で 、 ギルフォード・ザ・ライトニング を 焼き払わ れ たら 、 闇 の ゲーム で モンスター と 繋がっ てる 城之内 の 精神 まで 燃え尽き ちゃう ! お願い 、 死な ない で 城之内 ! あんた が 今 ここ で 倒れ たら 、 舞 さん や 遊戯 と の 約束 は どう なっ ちゃう の ? ライフ は まだ 残っ てる 。 ここ を 耐えれ ば 、 マリク に 勝てる ん だ から ! 次回 、 「 城之内 死す 」 。 デュエルスタンバイ !感想
Mecabがどうこうというよりsubprocessを紹介しただけみたいなところはあります!
- 投稿日:2019-06-22T12:14:58+09:00
はじめてのプロコンメモ(その4)
はじめに
AtCoder に登録したら次にやること ~ これだけ解けば十分闘える!過去問精選 10 問 ~の類題もやっています
第 4 問(200 点)問題を解いています。ABC 087 B - Coins
問題
あなたは、500円玉を A枚、100円玉を B枚、50円玉を C枚持っています。 これらの硬貨の中から何枚かを選び、合計金額をちょうど X円にする方法は何通りありますか。 同じ種類の硬貨どうしは区別できません。 2 通りの硬貨の選び方は、ある種類の硬貨についてその硬貨を選ぶ枚数が異なるとき区別されます。標準入力
2 2 2 100A = 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/9eed47f5483679fa66b1http://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)
- 投稿日:2019-06-22T11:45:03+09:00
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:23datetime形式をそのまま出力したときは、エクセルで開いたときにキレイじゃないです。
(エクセルのバージョンにもよるかも知れないですが。)
- 投稿日:2019-06-22T11:04:11+09:00
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のほうが行数かかるけど見やすいし早いからいっか!
- 投稿日:2019-06-22T10:47:03+09:00
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の解説を次回以降書きたいと思っています。
- 投稿日:2019-06-22T10:30:20+09:00
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
接続するとパスワードを聞かれるので、設定したパスワードを入力します。
- 投稿日:2019-06-22T10:21:02+09:00
出力引数はいずこへ...
背景と経緯
どうやら僕の頭の中には査読者が住んでおられるようです(※1).これは性分としか言いようがないのですが,なにがしかの文章を書いているときはほとんどかならず査読チェックが入ります.
つい今しがたも,初学者用の資料に「関数から返ってくる値のことを”出力引数”または”戻り値”という...」なんてことを何の気なしに書こうとしてしまったので,査読者から「それってほんとに同じものなの?中途半端な自分の知識だけで書こうとしてない?馬鹿なの?死ぬの?」というご指摘を受けてしまいました.もうしわけありません.さっそく「出力引数」と「戻り値」という二つのキーワードでググってみると,「“引数”とは関数に渡す値(=私が入力引数と認識しているもの)で,“戻り値”は関数から戻ってくる値」という説明が多いように思います.たとえば,こちらのサイト.
はて,私がプログラミングをかじり始めたのはかれこれ20年も前ですが(かじり続けて20年),そのときには「出力引数」とか「入力引数」とかって言ってた気がするんだけど,あれは幻だったのかしらん...自分の記憶に一抹の不安(唐松の文様,十四松の寝袋)を覚えたので,改めて「"出力引数"」で調べてみました(結果).
なんだ,あるではないか.引っかかってきたのは,MATLABやらScilabやらFortranやらの公式っぽいドキュメントですね.「出力引数」という日本語が存在していることは確認できましたが,「出力引数」と「戻り値」の関係はさっぱりわからん.というわけで,私なりに調べてみました.
まとめ
書いているとわりと長くなってしまったので,最初にまとめておくと以下のようになります.
出力引数と戻り値はおなじというのが現時点の結論です,しかし,引数には入力・出力とかの区別があったり,仮引数・実引数とかの区別があったりして,出力引数や戻り値たちの立ち位置はちょっとあいまいです.英語のほうは,入出力および仮・実の区別がはっきりとしていて,2つの軸に沿って言葉が使い分けられてわりとわかりやすいのです(以下参照).
一方,日本語は入出力および仮・実の区別を同時に行っていないようなので,曖昧さがうまれているように思います.とりあえず,ワタシの理解を,英語における区別と対応させて表にしました.
ここで,実引数および戻り値を「入力引数」と「出力引数」にそれぞれ対応させたのは,MATLABドキュメンテーションで,input arugumentの対訳が入力引数,output argumentの対訳が出力引数になっているのを参考にしました.そもそも,日本語で「引数」とした場合には「仮引数」なのか「実引数」なのかわかんないので,もういっそのこと
ってしちゃえばいいんじゃない?めんどくさいですね...すみません.
しらべてみたよ
といっても,googleとwikipediaをあたってみただけなのですが.
最初の手がかりにしたのはMATLABのドキュメンテーション.なぜMATLABかっていうと,僕が日常的によく使っているってのと,ドキュメンテーションがしっかりしている(商用なので無責任なことは書きますまい)という期待からです.んで,そのドキュメンテーションには「出力引数」の英訳として「output argument」っていうんがあるわけです.たとえば,こちら(日本語)とこちら(英語)を比較.
んで,google検索して引っかかってきたwikipediaのページが"Parameter (computer programming)"というページです.Wikipediaのサイト内検索で"output argument"を探しても,トップに出てくるのはこのページ.英語でも"output argument"は駆逐されてしまったのかと不安になりながら,件のページで"outpt argument"に関する記述をさがすと...ありました.
うーん.いまいちピンとこないです."output argument"と対になる"input argument"の記述を見てみると,
An input argument (the argument to an input parameter)とあります.ということは,アナロジーを駆使すると,
An output argument = the argument to an output parameterと類推できますね.
じゃあ,argumentとparameterの違いってなんやねんということになりますが,同じページに書いてありました.
なんだか,英語のほうがスッキリ区別できるような気がします.上記の記事によると,
・parameter (formal argument) = "variable"
・argument (actual argument or actural parameter) = "value"
ということらしいです.paramterは特定の値がassign(=代入)される(されうる)「入れ物」,argumentはassignされる値そのものという理解です.こうして理解すると,少なくとも英語には"value or not"と"in or out"という2つの軸がありそうです.表にするとこんな感じ.
スッキリ.
いやいや,僕が知りたかったのは日本語の「出力引数」なのでもうちょっとがんばります.上記の「parameterとargumentの違い」は日本語の「仮引数と実引数の違い」に対応しそうです.こちらでは仮引数と実引数の違いが解説されています.仮引数が"parameter"に対応し,実引数が"argument"に対応するようです.このように英語と日本語の対応を考えると,かねてからの懸案であった「出力引数」は,英語の"output argument"の対訳としてまったく問題がなさそうです.
そして,「戻り値」のほうですが,こちらでは,「関数が渡す値」となっております."output argument(出力引数)"が意味するものと同じと考えてよさそうです.
つまり,「出力引数」=「戻り値」
よかったよかった.おかえりなさい,出力引数.
これでワタシのなかの査読者にも納得してもらえる.
僕の記憶もあながち捨てたもんじゃなかったのね...あれ???
さきほどのページでは,「引数」という言葉は「関数に渡される」という意味で解説されています.関数から戻ってくるものへの言及は避けられています.冒頭で紹介したページも同様です.じゃあ,"output parameter"に対応する日本語ってどうなってんのでしょうか?
どうしよう.どなたかご存知でしたら教えてください.
さいごに
「出力引数」問題についてはワタシの頭の中の査読者をなんとか納得させることができました.でも,朝の貴重な原稿書きの時間の全てをこの記事に費やしてしまったために,ワタシの頭の中の指導教官に「進捗はどうした?」と詰められています.
生きづらい...
脚注
※1)しょせんワタシの中の査読者なので諸々の指摘抜けが発生します.この投稿に不正確な部分があっても怒らないでくdさい.やさしく教えて.
- 投稿日:2019-06-22T09:04:45+09:00
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 detailsgccをインストールすることで解決。
$ sudo apt-get install buid-essential2. 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 1Zlibが無いということでインストールして解決。
$ sudo apt-get install zlib1g-dev3. 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 1libffi-devをインストールすることで解決。
$ sudo apt-get install libffi-dev4. 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
- 投稿日:2019-06-22T09:04:45+09:00
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 detailsgccをインストールすることで解決。
$ sudo apt-get install buid-essential2. 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 1Zlibが無いということでインストールして解決。
$ sudo apt-get install zlib1g-dev3. 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 1libffi-devをインストールすることで解決。
$ sudo apt-get install libffi-dev4. 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
- 投稿日:2019-06-22T08:07:12+09:00
flaskアプリを、pdbを活用してデバッグする
手順
stack overflowのDebugging flask with pdbを参考にしています。
screenなどを使って2つ端末を立ち上げておきます。以降端末1、端末2と書きます。
flaskアプリ上のデバッグを開始したい箇所に、次のコードを埋め込みます。
import pdb; pdb.set_trace()端末1で、flaskのdevelopment用サーバをflask runにて起動します。下のようにFLASK_ENVを設定するとデバッグ出力モードになります。(参考:flask Development Server)
$ export FLASK_ENV=development $ flask runこの状態のまま、端末2で、curlコマンドで該当のアプリにアクセスします。
なお、curlの使い方は「curlコマンドの使い方 ~GET、POST、REST(json)の確認と、windowsでの利用手順」が分かりやすく参考になりました。そうすると、端末2(curl側)では待機状態になっているはずです。このまま端末1(flask側)を見るとpdbに入っていますので、後は端末1側でpdbにてデバッグすることができます。
環境
次でできました。難しい仕組みを使っていないので、広く活用できると思います。
flask: 1.0.2
python: 3.7.3
サーバ側のOS: linux(CentOS7)最後に
pdbはシンプルで便利なので、flaskアプリでもpdbでデバッグができて幸せでした。