【python3】タイムアウト設定

#!/usr/bin/env python3  
# -*- coding: utf-8 -*-

import sys
import time
from time_decorator import timeout, TimeoutError

class TimeoutDecoratorTest(object):
	def test(self, sleep_sec, timeout_sec):
		@timeout(timeout_sec)
		def inner_test():
			print("Start sleep " + str(sleep_sec) + " seconds.")
			print("Timeout in " + str(timeout_sec) + " seconds.")
			time.sleep(sleep_sec)
		try:
			inner_test()
			print("End sleep.")
		except TimeoutError:
			print("Timeout!")

if __name__ == '__main__':
	sleep_sec = int(sys.argv[1])
	timeout_sec = int(sys.argv[2])
	t = TimeoutDecoratorTest()
	t.test(sleep_sec, timout_sec)

タイムアウト処理を行うためのライブラリ
pip install wrap-timeout-decorator

import wrapt_timeout_decorator

@wrapt_timeout_decorator.timeout(dec_timeout=30)
def func():
while True:
pass

if __name__ == ‘__main__’:
func()

タイムアウトの設定をするのね

pythonのdebug

pdbを使用できる

import pdb

def factorial(n, sum=0):
	if n == 0:
		return sum

	pdb.set_trace()
	sum += n
	print(sum)
	return factorial(n-1, sum)

if __name__ == "__main__":
	factorial(5)
$ python3 test.py
> /home/vagrant/dev/test/test.py(8)factorial()
-> sum += n
(Pdb) bt
  /home/vagrant/dev/test/test.py(13)<module>()
-> factorial(5)
> /home/vagrant/dev/test/test.py(8)factorial()
-> sum += n
(Pdb) list
  3  	def factorial(n, sum=0):
  4  		if n == 0:
  5  			return sum
  6  	
  7  		pdb.set_trace()
  8  ->		sum += n
  9  		print(sum)
 10  		return factorial(n-1, sum)
 11  	
 12  	if __name__ == "__main__":
 13  		factorial(5)
(Pdb) 

Pythonのテストコード

# coding:utf-8

import unittest
import fizzbuzz as fb

class FizzBuzzTest(unittest.TestCase):
	def setUp(self):
		pass

	def tearDown(self):
		pass

	def test_normal(self):
		self.assertEqual(1, fb.fizzbuzz(1))

	def test_fizz(self):
		self.assertEqual("Fizz", fb.fizzbuzz(3))

	def test_buzz(self):
		self.assertEqual("Buzz", fb.fizzbuzz(5))

	def test_fizzbuzz(self):
		self.assertEqual("FizzBuzz", fb.fizzbuzz(3))

if __name__ == "__main__":
	unittest.main()

メインコード

# coding:utf-8

def fizzbuzz(number):
	if number % 15 == 0:
		return "FizzBuzz"
	if number % 5 == 0:
		return "Buzz"
	if number % 3 == 0:
		return "Fizz"

	return number

if __name__ == "__main__":
	for i in range(1, 101):
		print(fizzbuzz(i)) 

t$ python3 test_fizzbuzz.py
..F.
======================================================================
FAIL: test_fizzbuzz (__main__.FizzBuzzTest)
———————————————————————-
Traceback (most recent call last):
File “test_fizzbuzz.py”, line 23, in test_fizzbuzz
self.assertEqual(“FizzBuzz”, fb.fizzbuzz(3))
AssertionError: ‘FizzBuzz’ != ‘Fizz’
– FizzBuzz
+ Fizz

———————————————————————-
Ran 4 tests in 0.002s

FAILED (failures=1)

Pythonのpycファイルのマジックナンバー

Pythonファイル(平文ソースコード)をコンパイルするとpycファイルになる。
pythonユーザがpycファイルを作成する必要なし。モジュールとしてインポートされる場合に自動的に作成
元のモジュールが更新されると、次回インポート時にpycファイルも自動的に再作成

マジックナンバーとは、ファイルの種類を識別するため、ファイル先頭に付与する特別なバイト列。Pythonのバージョンごとにpycファイルのマジックナンバーが決まっている。

$ python3
Python 3.8.10 (default, Mar 15 2022, 12:22:08)
[GCC 9.4.0] on linux
Type “help”, “copyright”, “credits” or “license” for more information.
>>> import importlib.util
>>> importlib.util.MAGIC_NUMBER.hex()
‘550d0d0a’

Pythonでfor文を使って{辞書: [{辞書},{辞書},{辞書}…]}のjsonを作りたい

ありたいてに言うと、下記のような構造のjsonをfor文で作りたい

{
	"item": [
		{
			"area": "東京都","population": 1300, "capital": "東京"
		},
		{
			"area": "北海道","population": 538, "capital": "札幌市"
		},
		{
			"area": "沖縄","population": 143, "capital": "那覇市"
		}	
	]
}

for文で辞書を配列に入れて、それを辞書の中に入れてjsonにすればOK

ys = cl.OrderedDict()
result = []
for item in data:
	print(item["at"][:16] +" " + item["anm"] + " " + item["mag"] + " " + item["maxi"] + " " + item["cod"][:5] + " " + item["cod"][5:11]+ " " + item["cod"][12:-1])
	data = cl.OrderedDict()
	data["at"] = item["at"][:16]
	data["anm"] = item["anm"]
	data["mag"] = item["mag"]
	data["maxi"] = item["maxi"]
	data["tokei"] = item["cod"][:5]
	data["hokui"] = item["cod"][5:11]
	data["depth"] = item["cod"][12:-1]

	result.append(data)

ys["item"] = result
print(ys)

with open("test.json", "w") as f:
    json.dump(ys, f, ensure_ascii=False)

pythonによるjson操作と辞書の理解が浅かったので、これ作るのに丸一日かかった orz…
なんてこったい

Pythonでjson作成

import json

str = {
	"東京":{
		"population": 1300,
		"capital": "東京"
	},
	"北海道": {
		"population": 538,
		"capital": "札幌市"
	},
	"沖縄":{
		"population": 143,
		"capital": "那覇市"
	}
}

with open("population.json", "w") as f:
	json.dump(str, f, ensure_ascii=False)

{“東京”: {“population”: 1300, “capital”: “東京”}, “北海道”: {“population”: 538, “capital”: “札幌市”}, “沖縄”: {“population”: 143, “capital”: “那覇市”}}

なるほどー

[自然言語処理] チャットボット基礎

ChatterBot:
The program selects the closest matching response by searching for the closest matching known statement that matches the input, it then returns the most likely response to that statement based on how frequently each response is issued by the people the bot communicates with.

chat.txt

こんにちは
こちらこそ こんにちは
今日もよろしくお願いします

chat2.txt

こんばんは
こちらこそ こんばんは
もう眠いですね
おやすみなさい

main.py

from chatterbot import ChatBot 
from chatterbot.trainers import ListTrainer

bot = ChatBot("チャットボット試作品")

training_ = open('chat.text','r').readlines()
training2_ = open('chat2.text','r').readlines()

trainer = ListTrainer(bot)

trainer.train(training_)
trainer.train(training2_)

while True:
	try:
		bot_input = bot.get_response(input())
		print(bot_input)
	except(KeyboardInterrupt, EOFError, SystemExit):
		break

$ pip3 install chatterbot
$ pip3 install chatterbot-corpus
$ python3 main.py
[nltk_data] Downloading package stopwords to
[nltk_data] /home/vagrant/nltk_data…
[nltk_data] Package stopwords is already up-to-date!
[nltk_data] Downloading package averaged_perceptron_tagger to
[nltk_data] /home/vagrant/nltk_data…
[nltk_data] Package averaged_perceptron_tagger is already up-to-
[nltk_data] date!
List Trainer: [####################] 100%
List Trainer: [####################] 100%
こんにちは
こちらこそ こんにちは
もう眠いですね
おやすみなさい
もう眠いですね
おやすみなさい
こちらこそ こんばんは
もう眠いですね
aaa
もう眠いですね
そうですか
こちらこそ こんばんは
おはよう
もう眠いですね
こんにちは
こちらこそ こんにちは

なんだこれ…

[Python] labelImageを使って運転免許証を読み込み

lavelImageをやり直します

import os
os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = "data/vision.json"

import io
import cv2
import matplotlib.pyplot as plt
import matplotlib
from google.cloud import vision
import xml.etree.ElementTree as ET

img = cv2.imread("img/license.jpeg")

client = vision.ImageAnnotatorClient()
with io.open("img/license.jpeg", 'rb') as image_file:
	content = image_file.read()
image = vision.Image(content=content)
response = client.document_text_detection(image=image)

text_infos = []
document = response.full_text_annotation
for page in document.pages:
  for block in page.blocks:
    for paragraph in block.paragraphs:
      for word in paragraph.words:
        for symbol in word.symbols:
          bounding_box = symbol.bounding_box
          xmin = bounding_box.vertices[0].x
          ymin = bounding_box.vertices[0].y
          xmax = bounding_box.vertices[2].x
          ymax = bounding_box.vertices[2].y
          xcenter = (xmin+xmax)/2
          ycenter = (ymin+ymax)/2
          text = symbol.text
          text_infos.append([text, xcenter, ycenter])

tree = ET.parse("data/license.xml")
root = tree.getroot()
result_dict = {}
for obj in root.findall("./object"):
  name = obj.find('name').text
  xmin = obj.find('bndbox').find('xmin').text
  ymin = obj.find('bndbox').find('ymin').text
  xmax = obj.find('bndbox').find('xmax').text
  ymax = obj.find('bndbox').find('ymax').text
  xmin, ymin, xmax, ymax = int(xmin), int(ymin), int(xmax), int(ymax)
  texts = ''
  for text_info in text_infos:
    text = text_info[0]
    xcenter = text_info[1]
    ycenter = text_info[2]
    if xmin <= xcenter <= xmax and ymin <= ycenter <= ymax:
      texts += text
  result_dict[name] = texts
  
for k, v in result_dict.items():
    print('{} : {}'.format(k, v))

$ python3 app.py
name : 日本花子
birthday : 昭和61年5月1日生)
address : 東京都千代田区霞加喂2-1-2
data of issue : 令和01年05月07日12345
expiration date : 12024年(今和06年)06月01日未有动
driver license : 運転免許証
number : 第012345678900号
Public Safety Commission : 00000公安委員会

Finally
やっと来たね
というか、サイズが一定なら免許証以外でもOCRできるね

[Ubuntu] tesseractをinstallして使いたい

$ sudo apt -y install tesseract-ocr tesseract-ocr-jpn libtesseract-dev libleptonica-dev tesseract-ocr-script-jpan tesseract-ocr-script-jpan-vert
$ tesseract -v
tesseract 4.1.3
leptonica-1.79.0
libgif 5.1.4 : libjpeg 8d (libjpeg-turbo 2.0.3) : libpng 1.6.37 : libtiff 4.1.0 : zlib 1.2.11 : libwebp 0.6.1 : libopenjp2 2.3.1
Found AVX2
Found AVX
Found SSE
Found libarchive 3.4.0 zlib/1.2.11 liblzma/5.2.4 bz2lib/1.0.8 liblz4/1.9.2 libzstd/1.4.4
$ tesseract –list-langs
List of available languages (5):
Japanese
Japanese_vert
eng
jpn
osd
※osdとは、言語の判定、文字角度の識別を行う

$ tesseract test1.png output
->
$ tesseract test1.png stdout
Hello world
$ tesseract test2.png stdout -l jpn
こんにちは

### Pythonで使えるようにする
$ pip3 install pyocr

from PIL import Image
import sys
import pyocr

tools = pyocr.get_available_tools()
langs = tools[0].get_available_languages()

img = Image.open('test1.png')
txt = tools[0].image_to_string(
	img,
	lang=langs[0],
	builder=pyocr.builders.TextBuilder(tesseract_layout=6)
)
print(txt)

※tesseract_layout=6 が精度に重要

$ python3 main.py
Hello world

lang=’jpn’に変更すると、日本語も出力できる
$ python3 main.py
とこんにちは
|
tesseract_layout=3で実行すると…
$ python3 main.py
こんにちは

#### tesseract_layoutの意味
0 = Orientation and script detection (OSD) only.
1 = Automatic page segmentation with OSD.
2 = Automatic page segmentation, but no OSD, or OCR
3 = Fully automatic page segmentation, but no OSD. (Default)
4 = Assume a single column of text of variable sizes.
5 = Assume a single uniform block of vertically aligned text.
6 = Assume a single uniform block of text.
7 = Treat the image as a single text line.
8 = Treat the image as a single word.
9 = Treat the image as a single word in a circle.
10 = Treat the image as a single character.

0 =方向とスクリプトの検出(OSD)のみ。
1 = OSDによる自動ページセグメンテーション。
2 =自動ページセグメンテーション、ただしOSDまたはOCRなし
3 =完全自動のページセグメンテーション。ただし、OSDはありません。 (ディフォルト)
4 =可変サイズのテキストの単一列を想定します。
5 =垂直に配置されたテキストの単一の均一なブロックを想定します。
6 =単一の均一なテキストブロックを想定します。
7 =画像を単一のテキスト行として扱います。
8 =画像を1つの単語として扱います。
9 =画像を円の中の1つの単語として扱います。
10 =画像を1文字として扱います。

6で設定されているのが多いですね
文字角度を考慮しなければ3で、文字角度を考慮する場合は6でしょうか?
読み取りたい文字に併せて設定を変えながら試していくイメージか…

flaskをmysqlに接続

from flask import Flask, render_template
import pymysql

app = Flask(__name__)

def getConnection():
	return pymysql.connect(
		host="localhost",
		db="hoge",
		user="fuga",
		password="hou",
		charset="utf8",
		cursorclass=pymysql.cursors.DictCursor
	)

@app.route("/")
def index():

	connection = getConnection()

	sql = "SELECT * FROM avalanche where id = 1"
	cursor = connection.cursor()
	cursor.execute(sql)
	results = cursor.fetchall()

	cursor.close()
	connection.close()
	return render_template('index.html', results=results)

if __name__ == "__main__":
	app.run(debug=True, host='0.0.0.0', port=5000)

なるほど
これをdockerでやりたい