配列/リストの中身を一度にすべて表示する PHP, Python
- PHPを用いて次のようなコードで配列をループ処理せずに一度に全て表示する方法を調べてみました。
- PHP: implode()を用いると意図している感じに表示できます。
- PHP: vprintf()を用いても意図している感じに表示できるようです。
- Python: *でリストをアンパックしてprintに渡すと意図しているように表示できます。
PHPを用いて次のようなコードで配列をループ処理せずに一度に全て表示する方法を調べてみました。
<?php $chars = preg_split('//u', '配列の中身', -1, PREG_SPLIT_NO_EMPTY); foreach ($chars as $char) { echo $char, '<br>', PHP_EOL; } /* 配<br> 列<br> の<br> 中<br> 身<br> */
PHP: implode()
を用いると意図している感じに表示できます。
<?php $eol = '<br>' . PHP_EOL; $chars = preg_split('//u', '配列の中身', -1, PREG_SPLIT_NO_EMPTY); echo implode($eol, $chars), $eol; /* 配<br> 列<br> の<br> 中<br> 身<br> */
PHP: vprintf()
を用いても意図している感じに表示できるようです。
<?php $eol = '<br>' . PHP_EOL; $chars = preg_split('//u', '配列の中身', -1, PREG_SPLIT_NO_EMPTY); vprintf(str_repeat('%s' . $eol, count($chars)), $chars); /* 配<br> 列<br> の<br> 中<br> 身<br> */
vprintf()
の第1引数に用いるフォーマット%s<br>PHP_EOL
を配列$chars
と同じ数count($chars)
だけstr_repeat()
で用意しています。
print_r()
を使えば表示は行えますが、意図する形には行えません。
<?php $chars = preg_split('//u', '配列の中身', -1, PREG_SPLIT_NO_EMPTY); print_r($chars); /* Array ( [0] => 配 [1] => 列 [2] => の [3] => 中 [4] => 身 ) */
Python: *
でリストをアンパックしてprintに渡すと意図しているように表示できます。
# -*- coding: utf-8 -*- from __future__ import print_function eol = '<br>\n' chars = list(u'配列の中身') print(*chars, sep=eol, end=eol) ''' 配<br> 列<br> の<br> 中<br> 身<br> '''
- sepで区切り文字を
<br>\n
に変えています。
身
より前に表示されている<br>\n
です。 - endで文末の文字を
<br>\n
に変えています。
身
の後に表示されている<br>\n
です。
*
を付け忘れるとリストのまま表示されてしまいます。
*chars
のように*
を付ける事でリストがアンパックされるのでchars
のまま渡してしまうと意図しているようにはならないので注意が必要です。
- Python 2.7
[u'\u914d', u'\u5217', u'\u306e', u'\u4e2d', u'\u8eab']<br>
- Python 3.5
['配', '列', 'の', '中', '身']<br>
PythonでSQLite3を試す
Python2.7と3.5で動作するサンプルコードです。
SQLiteとは?
Oracle, MySQL, PostgreSQL, MariaDB などよりも軽量に動作し、アプリに組み込むなどして使われているようです。経験上デスクトップで確認したい場合や一時的に利用したい場合などに使うこともありました。SQLで操作します。メモリ管理も任せられるのでデータが多い場合、自前でテキストファイルで操作するよりもSQLiteを選択すると良い場合があります。
Python2 と Python3 で動作するサンプルコード
# -*- coding: utf-8 -*- import datetime, os, random, sqlite3, sys if __name__ != '__main__': sys.exit() db_file = 'example.db' base_dir = os.path.dirname(__file__) if not base_dir: base_dir = '.' db_path = base_dir + os.path.sep + db_file # db_pathが存在しなければTrue, 新規作成 db_is_new = not os.path.exists(db_path) # 新規作成時にINSERTするデータ def new_date(): for i in range(10): yield (i + 1, int(random.random() * 100), datetime.datetime.now()) # db_pathが無ければスクリプトと同じディレクトリ内に自動で作成 conn = sqlite3.connect(db_path) # db_pathが新たに作られた時 if db_is_new: # テーブル作成 conn.execute(''' CREATE TABLE example( id INTEGER, num INTEGER, date TEXT ) ''') try: # with文終了時はcommit with conn: # データ投入 conn.executemany(''' INSERT INTO example VALUES(?, ?, ?) ''', new_date()) except sqlite3.IntegrityError: # 例外発生時はrollback pass # カラム名で参照できるようにsqlite3.Rowを使用 conn.row_factory = sqlite3.Row # SELECTしたデータを1行ずつ出力 for row in conn.execute('SELECT * FROM example'): r = ['%s = %s' % (k, row[k]) for k in row.keys()] print(', '.join(r)) conn.close()
importで呼ばれた場合は終了します。
- このスクリプトは直接実行する前提ですのでimportで呼ばれた場合は終了します。
if __name__ != '__main__': sys.exit()
dbファイルはスクリプトと同じディレクトリ内にあるものとします。
os.path.dirname(__file__)
でスクリプトのあるディレクトリ部分を取得します。base_dir
がカラの際はカレントディレクトリを示す.
を代入します。os.path.sep
はOSで利用されているディレクトリの区切り文字で、Windowsなら\
になります。
db_file = 'example.db' base_dir = os.path.dirname(__file__) if not base_dir: base_dir = '.' db_path = base_dir + os.path.sep + db_file
dbファイルが無い場合は新規に作成されます。
- dbファイルの存在確認でまだファイルが無い場合、新たに作るものと判断しテーブルの作成などに利用します。
# db_pathが存在しなければTrue, 新規作成 db_is_new = not os.path.exists(db_path)
sqlite3.connect()
で取得するConnectionオブジェクトをコンテキストマネージャーとして利用しています。
try: # with文終了時はcommit with conn: pass except sqlite3.IntegrityError: # 例外発生時はrollback pass
- Python 2: http://docs.python.jp/2/library/sqlite3.html#using-the-connection-as-a-context-manager
- Python 3: http://docs.python.jp/3/library/sqlite3.html#using-the-connection-as-a-context-manager
conn.executemany()
で複数データをまとめてINSERTしています。
# 新規作成時にINSERTするデータ def new_date(): for i in range(10): yield (i + 1, int(random.random() * 100), datetime.datetime.now())
# データ投入 conn.executemany(''' INSERT INTO example VALUES(?, ?, ?) ''', new_date())
- サンプルコードでは第2引数にジェネレータを渡しています。
イテレータやタプルのリストを渡してまとめてデータ登録します。
TOHO シネマイレージ カード作成後、6本目の映画を見終わりました
TOHO シネマイレージ カードを作成してから6本目の映画を見終わりました。
次の1本は無料で見られるらしい。
TOHO シネマイレージ カードを作成してから見た映画の備忘録。
- TOHO シネマイレージ カードを作成してから見た映画の備忘録。
- 1. 貞子 vs 伽椰子
- 2. Independence Day: Resurgence
- 3. 君の名は。
- 4. Self/less
- 5. BFG
- 6. GANTZ:O
1. 貞子 vs 伽椰子
- ホラー映画を時々見たくなり、たまたま上映していた貞子 vs 伽椰子。
個人的には、それぞれのホラー映画を別々に見た方が怖いような気がしました。
2. Independence Day: Resurgence
- 前作のIndependence Dayは1996年に公開されていたそうです。『えっ、20年も前!?そんなに前だったっけ』という驚きです。
3. 君の名は。
- 何度も見たくなりました。(個人の感想)
実在する場所が登場したり、見たことのあるような景色を楽しむこともできるかもしれません。
Blu-rayで出たらおそらく買います。
4. Self/less
- 妙にシックス・デイを見たくなりました。
5. BFG
- 戸締りはしっかりしよう。
6. GANTZ:O
PythonでURLをパースする
Python2.7と3.5で動作するサンプルコードです。
Python2 と Python3 で動作するサンプルコード
- URLのパースに
urlparse
を利用します。 - params, queryのパースには
parse_qs
を利用します。
# -*- coding: utf-8 -*- from __future__ import print_function import sys # print(sys.version_info) ## 2.7: sys.version_info(major=2, minor=7, micro=11, releaselevel='final', serial=0) ## 3.5: sys.version_info(major=3, minor=5, micro=1, releaselevel='final', serial=0) if sys.version_info.major <= 2: # Python 2.7 from urlparse import urlparse, parse_qs else: # Python 3.5 from urllib.parse import urlparse, parse_qs parse = urlparse('https://www.example.com/file;p1=1;p1=2?encoding=UTF-8&q1=1&q1=2&q1=3&q2=#q=example') print(parse) # 2.7: ParseResult(scheme='https', netloc='www.example.com', path='/file', params='p1=1;p1=2', query='encoding=UTF-8&q1=1&q1=2&q1=3&q2=', fragment='q=example') # 3.5: ParseResult(scheme='https', netloc='www.example.com', path='/file', params='p1=1;p1=2', query='encoding=UTF-8&q1=1&q1=2&q1=3&q2=', fragment='q=example') p = parse_qs(parse.params) print(p) # 2.7: {'p1': ['1', '2']} # 3.5: {'p1': ['1', '2']} # 値がカラのパラメータは無視される q = parse_qs(parse.query) print(q) # 2.7: {'q1': ['1', '2', '3'], 'encoding': ['UTF-8']} # 3.5: {'q1': ['1', '2', '3'], 'encoding': ['UTF-8']} # parse_qs()の第2引数をTrueとすることで値がカラのパラメータも結果に含まれる q2 = parse_qs(parse.query, True) print(q2) # 2.7: {'q1': ['1', '2', '3'], 'q2': [''], 'encoding': ['UTF-8']} # 3.5: {'q2': [''], 'q1': ['1', '2', '3'], 'encoding': ['UTF-8']} for key in sorted(q.keys()): # 区切り文字`sep`の初期値は' '(半角スペース) # 文末`end`の初期値は'\n' print(key, '=', q[key], sep='\t', end=', ') # encoding = ['UTF-8'], q1 = ['1', '2', '3'], print() if 'q1' in q: # Python3 に dict.has_key() は無い for v in q['q1']: print(v, end=', ') # 1, 2, 3,
import文、from文の注意点
- import文は
import モジュール
- from文は
from モジュール import 関数
Python 2.6以降で3のprint()関数を利用できるようにする
from __future__ import print_function
を加えることでPython 2.7でPython 3スタイルのprint()関数を利用しています。
Python 2と3で読み込むモジュールを変える
- urlparse, parse_qs の含まれるモジュールがPython 2と3で異なるので、バージョンによって読み込むモジュールを変えています。
import sys if sys.version_info.major <= 2: # Python 2.7 from urlparse import urlparse, parse_qs else: # Python 3.5 from urllib.parse import urlparse, parse_qs
dict.has_key() は廃れた用法
- Python 3で
dict.has_key()
を使用するとAttributeErrorが発生します。
AttributeError: 'dict' object has no attribute 'has_key'
- dictにkeyがあるかどうかは
key in dict
でチェックします。
if key in dict: pass d = {'a':12} print('ok' if 'a' in d else 'ng') # ok
- 反対にdictにkeyがない場合のチェックは
key not in dict
で行えます。
if key not in dict: pass d = {'a':12} print('ok' if 'a' not in d else 'ng') # ng
各関数のドキュメント
urlparse
- 2.x用
urlparse.urlparse
- 3.x用
urllib.parse.urlparse
parse_qs
- 2.x用
urlparse.parse_qs
- 3.x用
urllib.parse.parse_qs
PHPで画像アップロードに関して注意するphp.iniの設定
ファイルアップロードに関する設定
file_uploads
初期値 1
ファイルアップロードを有効にするかどうか。upload_max_filesize
初期値 "2M"
アップロードできる1ファイルあたりの最大サイズ。max_file_uploads
初期値 20
同時にアップロードできるファイルの最大数。
データ処理に関する設定
post_max_size
初期値 "8M"
POSTできる最大サイズ。
それぞれの設定を確認
php.ini
ファイルを見る場合、ファイルの場所が不明な際php --ini
とすることでiniファイルの場所を確認できます(少なくとも5.6.22では。)
$ php --ini
- 個々のディレクティブの状況確認は次のコードを実行。
<?php $settings = ['file_uploads', 'upload_max_filesize', 'max_file_uploads', 'post_max_size']; foreach ($settings as $name) { echo $name, ' = ', ini_get($name), '<br/>', "\n"; }
- 初期値のままなら画面上に次のように出力されます。
file_uploads = 1 upload_max_filesize = 2M max_file_uploads = 20 post_max_size = 8M
Pythonでテキストファイルを読み込む
プレーンなテキストファイルをwith構文で読み込む時に試したメモです。
以前挑戦したCSVモジュールを利用してのTSVファイルを読み込む方法はこちら。
Windowsのコマンドプロンプト上で動かしたため、出力に用意したテキストファイルはShift_JISとしています。
- sjis.txt
あ い う え お
目次
1行ずつ読み込む iterator
# -*- coding: utf-8 -*- from __future__ import print_function with open('sjis.txt') as f: for line in f: print(line, end='')
- Python 2.7 での実行結果
あ い う え お
- Python 3.5 での実行結果
あ い う え お
特別な理由が無ければiteratorを利用して1行ずつ読み込む方法で十分なようですが、iteratorを利用しない方が良い場合もあるようです。
全部読み込む read()
# -*- coding: utf-8 -*- from __future__ import print_function with open('sjis.txt') as f: print(f.read(), end='')
- Python 2.7 での実行結果
あ い う え お
- Python 3.5 での実行結果
あ い う え お
数GBにもおよぶログファイルなどはメモリが足りなくなりそうです。
リストとして全部読み込む readlines()
# -*- coding: utf-8 -*- from __future__ import print_function with open('sjis.txt') as f: print(f.readlines())
- Python 2.7 での実行結果
['\x82\xa0\n', '\x82\xa2\n', '\x82\xa4\n', '\x82\xa6\n', '\x82\xa8\n']
- Python 3.5 での実行結果
['あ\n', 'い\n', 'う\n', 'え\n', 'お\n']
1行だけ読み込む readline()
# -*- coding: utf-8 -*- from __future__ import print_function with open('sjis.txt') as f: print(f.readline(), end='')
- Python 2.7 での実行結果
あ
- Python 3.5 での実行結果
あ
いずれの方法も末尾の改行コードまで含まれています。
末尾の改行コードが不要な場合はrstrip()
で除去などを行う必要があります。
Pythonで排他ロックしてファイルに書き込む
排他ロックとは?
排他ロックしてファイルを壊れ難くしてみます。
目次
排他ロックしてファイルに書き込む
Pythonではfcntl
モジュール(2.x)(3.x)を利用します。
※WindowsではサポートされていないのでWindowsでは動作しません。
※r+
の読み書きモードでは新たにファイルは作られません。あらかじめカラのtest.txt
を用意します。
# -*- coding: utf-8 -*- import fcntl, os filename = 'test.txt' # ファイルを読み書きモードで開く with open(filename, 'r+') as f: try: # ファイルを排他ロックする fcntl.flock(f, fcntl.LOCK_EX) # ファイルから読み込む data = f.readlines() # ファイルを切り詰める f.truncate(0) # ファイルの位置をリセット f.seek(os.SEEK_SET) # データを加える data.append('hoge\n') # ファイルに書き込む f.writelines(data) except IOError: print('flock() failure')