python3でメール送信

#!/bin/env python3

import smtplib
from email.mime.text import MIMEText
import datetime

jp='iso-2022-jp'

raw_msg = "hogehoge"
msg = MIMEText(raw_msg.encode(jp), 'plain', jp,)

fromaddr = "hoge"
toaddr = "hogehoge"

d = datetime.datetime.today()
date = d.strftime("%Y-%m-%d")

msg['Subject'] = date
msg['From'] = fromaddr
msg['To'] = toaddr

try:
	server = smtplib.SMTP("localhost")
	server.send_message(msg)
	print("successfully sent email")
except Exception:
	print("Error: unable to send email")

[vagrant@localhost python]$ python3 mail.py
successfully sent email

あれ、こない。vagrantだから? ec2でやってみるか。

ec2からコマンドを打つ
[ec2-user@ip-***-**-**-** html]$ python3 mail.py
successfully sent email

なに、こない。

pythonからsqliteに接続する

import sqlite3

dbpath = "test.sqlite"
conn = sqlite3.connect(dbpath)

cur = conn.cursor()
cur.executescript("""
DROP TABLE IF EXISTS items;

CREATE TABLE items(
	item_id INTEGER PRIMARY KEY,
	name TEXT UNIQUE,
	price INTEGER
);
INSERT INTO items(name, price)VALUES('Apple', 800);
INSERT INTO items(name, price)VALUES('Orange', 780);
INSERT INTO items(name, price)VALUES('Banana', 430);
""")

conn.commit()

cur = conn.cursor()
cur.execute("SELECT item_id, name, price FROM items")
item_list = cur.fetchall()
for it in item_list:
	print(it)

[vagrant@localhost python]$ python3 app.py
(1, ‘Apple’, 800)
(2, ‘Orange’, 780)
(3, ‘Banana’, 430)

import sqlite3

filepath = “test2.sqlite”
conn = sqlite3.connect(filepath)

cur = conn.cursor()
cur.execute(“DROP TABLE IF EXISTS items”)
cur.execute(“”” CREATE TABLE items(
item_id INTEGER PRIMARY KEY,
name TEXT,
price INTEGER)”””)
conn.commit()

cur = conn.cursor()
cur.execute(
“INSERT INTO items (name,price) VALUES (?,?)”,
(“Orange”, 520))
conn.commit()

cur = conn.cursor()
data = [(“Mango”, 770), (“Kiwi”,400), (“Grape”,800),(“Peach”,940),(“Persimmon”,700),(“Banana”, 400)]
cur.executemany(
“INSERT INTO items(name,price) VALUES(?,?)”, data)
conn.commit()

cur = conn.cursor()
price_range = (400, 700)
cur.execute(
“SELECT * FROM items WHERE price>=? AND price<=?", price_range) fr_list = cur.fetchall() for fr in fr_list: print(fr) [/python] [vagrant@localhost python]$ python3 app.py (1, 'Orange', 520) (3, 'Kiwi', 400) (6, 'Persimmon', 700) (7, 'Banana', 400)

csvファイルを読み込む

文字コードがshift-jsだと、
[vagrant@localhost python]$ python3 app.py
Traceback (most recent call last):
File “app.py”, line 4, in
csv = codecs.open(filename, “r”, “shift_jis”).read()
File “/home/vagrant/.pyenv/versions/3.5.2/lib/python3.5/codecs.py”, line 698, in read
return self.reader.read(size)
UnicodeDecodeError: ‘shift_jis’ codec can’t decode byte 0xef in position 0: illegal multibyte sequence

utf-8にします。

import codecs

filename = "list-sjis.csv"
csv = codecs.open(filename, "r", "utf-8").read()

data = []
rows = csv.split("\r\n")
for row in rows:
	if row == "": continue
	cells = row.split(",")
	data.append(cells)

for c in data:
	print(c[1], c[2])

[vagrant@localhost python]$ python3 app.py
商品名 値段
石鹸 300
手袋 150
マスク 230

import csv, codecs

filename = "list-sjis.csv"
fp = codecs.open(filename, "r", "utf-8")

reader = csv.reader(fp, delimiter=",", quotechar='"')
for cells in reader:
	print(cells[1], cells[2])

このようにも書けますね。

pyyaml

[vagrant@localhost python]$ pip3 install pyyaml
Collecting pyyaml
Downloading https://files.pythonhosted.org/packages/9e/a3/1d13970c3f36777c583f136c136f804d70f500168edc1edea6daa7200769/PyYAML-3.13.tar.gz (270kB)
100% |████████████████████████████████| 276kB 507kB/s
Installing collected packages: pyyaml
Running setup.py install for pyyaml … done
Successfully installed pyyaml-3.13

import yaml

yaml_str = """
Date: 2018-08-10
PriceList:
	-
		item_id: 1000
		name: Banana
		color: yellow
		price: 800
	-
		item_id: 1001
		name: Orange
		color: orange
		price: 1400
	-
		item_id: 1002
		name: Apple
		color: red
		price: 2400
"""

data = yaml.load(yaml_str)

for item in data['PriceList']:
	print(item["name"], item["price"])

yaml.scanner.ScannerError: while scanning for the next token
found character ‘\t’ that cannot start any token
in ““, line 4, column 1:

^
何故だ?

import yaml

customer = [
	{ "name": "Yamada", "age": "35", "gender": "man"},
	{ "name": "Sato", "age": "58", "gender": "woman"},
	{ "name": "Kato", "age": "42", "gender": "man"},
	{ "name": "Nishi", "age": "22", "gender": "man"}
]

yaml_str = yaml.dump(customer)
print(yaml_str)
print("--- --- ---")

data = yaml.load(yaml_str)

for p in data:
	print(p["name"])

書き出しは出来ますね。

[vagrant@localhost python]$ python3 app.py
– {age: ’35’, gender: man, name: Yamada}
– {age: ’58’, gender: woman, name: Sato}
– {age: ’42’, gender: man, name: Kato}
– {age: ’22’, gender: man, name: Nishi}

— — —
Yamada
Sato
Kato
Nishi

import yaml

yaml_str = """
color_def:
		- &color1 "#FF0000"
		- &color2 "#00FF00"
		- &color3 "#0000FF"

color:
	title: *color1
	body: *color2
	link: *color3
"""

data = yaml.load(yaml_str)
print("title=", data["color"]["title"])
print("body=", data["color"]["body"])
print("link=", data["color"]["link"])

yaml.scanner.ScannerError: while scanning for the next token
found character ‘\t’ that cannot start any token
in ““, line 3, column 1:
– &color1 “#FF0000”
なんだこれ?

jsonを扱う

import urllib.request as req
import os.path, random
import json

url = "hoge"
savename = "hogehoge"
if not os.path.exists(url):
	req.urlretrieve(url, savename)

data = json.load(open(savename, "r", encoding="utf-8"))

r = random.choice(data)
print(r['kami'], r['simo'])

jsonを作る。

import json

price = {
	"date": "2018-08-11",
	"price": {
			"apple": 80,
			"orange": 55,
			"banana": 40
	}
}
s = json.dumps(price)
print(s)

[vagrant@localhost python]$ python3 app.py
{“price”: {“apple”: 80, “orange”: 55, “banana”: 40}, “date”: “2018-08-11”}

pythonでxmlを解析

横浜市の防災拠点

from bs4 import BeautifulSoup
import urllib.request as req
import os.path

url = "http://www.city.yokohama.lg.jp/somu/org/kikikanri/data/shelter.xml"
savename = "shelter.xml"
if not os.path.exists(savename):
	req.urlretrieve(url, savename)

xml = open(savename, "r", encoding="utf-8").read()
soup = BeautifulSoup(xml, 'html.parser')

info = {}
for i in soup.find_all("shelter"):
	name = i.find("name").string
	ward = i.find("ward").string
	addr = i.find("address").string
	note = i.find("notes").string
	if not (ward in info):
		info[ward] = []
	info[ward].append(name)

for ward in info.keys():
	print("+", ward)
	for name in info[ward]:
		print("| - ", name)

[vagrant@localhost python]$ python3 app.py
+ 磯子区
| – 滝頭小学校
| – 岡村小学校
| – 磯子小学校
| – 浜小学校
| – 杉田小学校
| – 根岸小学校
| – 屏風浦小学校
| – 梅林小学校
| – 汐見台小学校
| – 洋光台第一小学校
| – 洋光台第二小学校
| – さわの里小学校
| – 洋光台第三小学校
| – 洋光台第四小学校
| – 森東小学校
| – 山王台小学校

なるほど。xmlを作って公開したいですな。

<?php

$rootNode = new SimpleXMLElement("<rss xmlns:a10='http://www.w3.org/2005/Atom' version='2.0'><items></items>");

$itemNode = $rootNode->addChild('item');
$itemNode->addChild('title', '剰余金の配当に関するお知らせ');
$itemNode->addChild('description', '剰余金の配当を行うことを決議いたしました。');

$itemNode = $rootNode->addChild('item');
$itemNode->addChild('title', '監査役の異動に関するお知らせ');
$itemNode->addChild('description', '定時株主総会に付議する監査役の候補者につきまして、下記の通り内定いたしました。');

$itemNode = $rootNode->addChild('item');
$itemNode->addChild('title', '自己株式の取得状況に関するお知らせ');
$itemNode->addChild('description', '自己株式取得状況について、下記のとおりお知らせいたします。');

// $itemNode->addAttribute('stock', 'none');
$dom = new DOMDocument('1.0');
$dom->loadXML($rootNode->asXML());
$dom->formatOutput = true;
echo $dom->saveXML();

[Sat Aug 11 20:12:20 2018] 192.168.35.1:53532 [500]: /app.php – Uncaught exception ‘Exception’ with message ‘String could not be parsed as XML’ in /home/vagrant/python/app.php:3
Stack trace:
#0 /home/vagrant/python/app.php(3): SimpleXMLElement->__construct(‘


剰余金の配当に関するお知らせ
剰余金の配当を行うことを決議いたしました。


監査役の異動に関するお知らせ
定時株主総会に付議する監査役の候補者につきまして、下記の通り内定いたしました。


自己株式の取得状況に関するお知らせ
自己株式取得状況について、下記のとおりお知らせいたします。


[/php]

*.bin

バイナリーデータをつくる。
バイナリーデータ:コンピュータが処理・記憶するために2進化されたファイル

filename = "a.bin"
data = 100
with open(filename, "wb") as f:
	f.write(bytearray([data]))

[vagrant@localhost python]$ hexdump a.bin
0000000 0064
0000001

binary dataを見よう

binary data バイナリーファイルのデータを16進数や8進数で出力する

なんじゃこりゃー
[vagrant@localhost python]$ hexdump index.html
0000000 213c 4f44 5443 5059 2045 7468 6c6d 3c3e
0000010 7468 6c6d 6c20 6e61 3d67 6a22 2261 3c3e
0000020 6568 6461 3c3e 656d 6174 6320 6168 7372
0000030 7465 223d 7475 2d66 2238 3c3e 696c 6b6e
0000040 7220 6c65 223d 7473 6c79 7365 6568 7465
0000050 2022 7268 6665 223d 7363 2f73 7473 6c79
0000060 2e65 7363 2273 3c3e 6974 6c74 3e65 82e3
0000070 e3a2 a183 83e3 e380 b982 2f3c 6974 6c74
0000080 3e65 2f3c 6568 6461 3c3e 6f62 7964 3c3e
0000090 3168 e33e a282 83e3 e3a1 8083 82e3 e5b9
00000a0 a885 9be5 3cbd 682f 3e31 683c 3e72 733c
00000b0 6365 6974 6e6f 6920 3d64 7422 706f 3e22
00000c0 683c 3e32 99e9 e68d b4b0 87e9 3c8f 682f
00000d0 3e32 693c 676d 6320 616c 7373 223d 6d69
00000e0 6761 2265 7320 6372 223d 692f 616d 6567
00000f0 722f 6961 2e6e 6e70 2267 3c3e 732f 6365
0000100 6974 6e6f 3c3e 6573 7463 6f69 206e 6469
0000110 223d 6f74 2270 3c3e 3268 e63e 97b0 b8e6
0000120 3ca9 682f 3e32 693c 676d 6320 616c 7373
0000130 223d 6d69 6761 2265 7320 6372 223d 692f
0000140 616d 6567 742f 6d65 2e70 6e70 2267 3c3e
0000150 732f 6365 6974 6e6f 3c3e 6573 7463 6f69
0000160 206e 6469 223d 6f74 2270 3c3e 3268 e93e
0000170 a8a2 90e5 e391 bb83 a2e9 e9a8 9f80 2f3c
0000180 3268 3c3e 6d69 2067 6c63 7361 3d73 6922
0000190 616d 6567 2022 7273 3d63 2f22 6d69 6761
00001a0 2f65 6977 646e 702e 676e 3e22 2f3c 6573
00001b0 7463 6f69 3e6e 2f3c 6f62 7964 3c3e 682f
00001c0 6d74 3e6c
00001c4

そういえばマーケットスピードでtickerを複数画面で閲覧できるように編集する場合もバイナリーデータを編集しますよね。

為替データを取得して保存する

import urllib.request as request
import datetime
import json

API = "hoge"
json_str = request.urlopen(API).read().decode("utf-8")
data = json.loads(json_str)
print("1USD="+data["JPY"]+"JPY")

t = datetime.date.today()
fname = t.strftime("%Y-%m-%d") + ".json"
with open(fname, "w", encoding="utf-8") as f:
	f.write(json_str)

[vagrant@localhost python]$ python3 app.py
1USD=111.13473JPY

入ってますね。なるほど、datetime.date.today()か、datetime.strftime(datetime.now(),”%Y%m%d%H%M%S”)で時間を取得していましたが、日付だけならtodayで十分ですね。

コインチェックのデータを取りたい。
https://coincheck.com/ja/documents/exchange/api#about
https://coincheck.com/api/ticker

ん?
[vagrant@localhost python]$ python3 app.py
Traceback (most recent call last):
File “app.py”, line 8, in
print(“bid=”+data[“bid”]+”JPY, ask=”+data[“ask”])
TypeError: Can’t convert ‘float’ object to str implicitly

floatは駄目だと?書き直します。

print("bid="+str(data["bid"])+"JPY, ask="+str(data["ask"]))

なるほど。
[vagrant@localhost python]$ python3 app.py
bid=731751.0JPY, ask=732169.0

Vue.jsを触ってみよう

CDNで読み込みます。

<script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script>
<div id="demo">
	<p>{{message}}</p>
	<input v-model="message">
</div>

<script>
	var demo = new Vue({
		el: "#demo",
		data: {
			message: "hello Vue.js!"
		}
	})
</script>

Ajaxのような動きをする。
CDNのvue.jsの中を見てみる。
https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js

XMLHttpRequestがないのでAjaxではないのか。。これだけではちょっとわかりません。

v-modelは双方向データバインディング
v-ifはifでレンダリング
v-onはv-on:click=”doSomething”など、イベントリスナ
v-forはfor文

<script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script>
<div id="demo">
	<li v-for="item in items">
		{{item.message}}
	</li>
</div>

<script>
	var demo = new Vue({
		el: "#demo",
		data: {
			items: [
				{message: 'Foo'},
				{message: 'Bar'}
			]
		}
	})
</script>

なるほど。書きやすそうな印象はありますね。