文字列でメソッド名があるかどうか確認し、あれば実行する
is_callable = callable(getattr(obj, name, None))
でメソッド名があるかどうかBoolean値で得られるので
if callable(getattr(obj, name, None)):
getattr(obj,name)(param)
でおk
- How to check whether a method exists in Python?
- Python using getattr to call function with variable parameters
リスト内包表現を用いて2次元配列を1次元に変換
d2を2次元配列として
d1 = [x for sublist in d2 for x in sublist]
でおk
参考:Convert multi-dimensional list to a 1D list in Python
pyenvをUbuntuにインストール
なんか色々依存関係があるので、先にこれを実行
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
githubからpyenvをダウンロード
$ git clone https://github.com/yyuu/pyenv.git ~/.pyenv
設定
export PYENV_ROOT=$HOME/.pyenv
export PATH=$PYENV_ROOT/bin:$PATH
eval "$(pyenv init -)"
pythonインストール(3.6.0をインストール)
$ pyenv install 3.6.0
globalきりかえ
$ pyenv global 3.6.0
参考: + Common build problems + Pyenvの使い方
max() arg is an empty sequence
Python3.4からdefault引数が使える
>>> max([], default=100)
100
参考:A safe max() function for empty lists
pythonとteeコマンドを組み合わせて出力を画面で見ながらファイルにも書き出す
pythonは-uオプションを使うと良い
$ python -u hoge.py | tee hoge.log
追記なら
$ python -u hoge.py | tee -a hoge.log
参考: Python3 と tee コマンドを組み合わせたときにハマった
文字列を反転する
>>> hoge = 'abc'
>>> hoge[::-1]
cba
参考: Python で文字列反転 - 似非プログラマの覚え書き
リストの注意点
参照渡しされること。 値渡しするにはスライスかディープコピーしないといけない。 スライスで良さそう。
>>> hoge = [1,2,3]
>>> fuga = hoge[:]
参照:Python のリストの扱いで注意すること - Qiita
リストを日付でソート
参考: Python でリストのソートまとめ - akiyoko blog
lambda式とか使える。日付の入った要素があったりして、日付でソートしたい場合は
from datetime import datetime
not_sort_list = [
{'id':1, 'date':datetime(2017,10,20,0,0,0)},
{'id':2, 'date':datetime(2017,10,19,0,0,0)},
{'id':3, 'date':datetime(2017,10,29,0,0,0)},
{'id':4, 'date':datetime(2017,10,19,0,0,0)}
]
sorted_list = sorted(not_sort_list, key=lambda x: int(x['date'].timestamp()))
これで日付順でソートできる
※ python3
データをJSONファイルで保存する
json.dumps()でいけるが、要素にdatetimeなどが入っているとjson化してくれないのでちょっと手間が必要
参考: + 第11回 標準になったjsonモジュール:Python 3.0 Hacks|gihyo.jp … 技術評論社 + pythonでjson出力する際で対応していない型(e.g. datetime)の値を変換しながら出力したい - Qiita + Pythonオブジェクトをシリアライズする - Dive Into Python 3 日本語版
def datetime_to_str(self, o):
if isinstance(o, datetime):
return o.isoformat()
raise TypeError(repr(o) + " is not JSON serializable")
def str_to_datetime(self, o):
if "date" in o:
o["date"] = datetime.strptime(o["date"],"%Y-%m-%dT%H:%M:%S")
return o
f = "dump.json"
with open(f,'w',encoding='utf-8') as f:
json.dump(sorted_list,f,default=datetime_to_str)
data = ""
if os.path.exists(f):
with open(f,'r') as f:
data = json.load(f, object_hook=str_to_datetime)
日時の差分を秒単位で出す
参考:pythonで日時の差分を秒単位で出す方法 - Qiita
from datetime import datetime
from_date = datetime(2017,10,20,0,0,0)
to_date = datetime(2017,10,21,0,0,0)
print (to_date - from_date).total_seconds()
リストから重複を省く
参考:Python Tips:リストから重複した要素を削除したい - Life with Python
list(set(sorted_list))
uniq_list = []
for x in sorted_list:
if x not in uniq_list:
uniq_list.append(x)
他にもあるけど、まだ使ってない。
pip freezeでWarning: cannot find svn location for distribute==0.6.24dev-r0
$ sudo pip install --upgrade distribute
でおk
pipで一気にインストールする
pip freezeで出てくる出力をファイルに書き出したものを使うと、別の環境で同じ状態にもっていける。ファイルからバージョン情報を消すと最新の状態でインストール出来る。
$ pip install -r freezed.txt
for文でループカウント取得
参考Python 配列をfor文でまわしているときのループカウント取得 : fujishinko 雑記帳
for i,item in enumerate(['a','b','c']):
print i,item
日本語のコマンドライン引数取得
参考Python: コマンドライン引数の取得 – sys.argv変数
#hoge.py
# -\*- encoding: utf-8 -\*-
import sys
argv = sys.argv
print argv[1].decode("utf-8")
$ python hoge.py あいうえお
あいうえお
$
コマンド実行して実行結果を取得
参考Python の subprocess で出力を受け取るときは communicate() を使おう - Qiita subprocessを使う。何か昔は別の手法だったらしい。
import subprocess
p = subprocess.Popen("echo 'hoge'",shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
p.wait()
stdout_data,stderr_data = p.communicate()
print stdout_data.decode("utf-8").strip()
親クラスのメソッド呼び出し
class Hoge(object):
def aaa(self,param):
print param
class Fuga(Hoge):
def bbb(self,param):
self.hage = super(Fuga,self).aaa(param)
f = Fuga()
f.bbb('test')
こんな感じ。お作法を忘れがち。
正規表現オブジェクトのパターンをチェックする方法
他のライブラリで正規表現が設定されてて、その内容をチェックしたかったので調べてみたら、patternプロパティを見れば良いらしい
import re
r = re.compile('^hoge',re.l)
print r.pattern
参考:How to print SRE_Pattern (regexp object) text for debugging purposes? - comp.lang.python
1ヶ月前の日付を求める
timedeltaを使うとweeksとかdaysしか指定出来ないので、1ヶ月前の日付を取得しようと思ったら、別の方法が必要になる
import time
from datetime import date
base_date = date(2015,1,3)
one_month_ago = date.fromtimestamp(time.mktime((base_date.year, base_date.month -1, base_date.day, 0, 0, 0, 0, 0, 0)))
こんな感じで出来る。 参考:[Python] 月の加減算処理ができない? | それなりブログ
日付表示で良く使うフォーマット
from datetime import date
print date(2002,12,4).isoformat()
としておくと、2002-12-04と表示される
lxmlをインストールしようとしたら、fatal error: libxml/xmlversion.h: No such file or directory
ライブラリが足らないのでインストールすればおk python 2.7 - src/lxml/etree_defs.h:9:31: fatal error: libxml/xmlversion.h: No such file or directory - Stack Overflow
$ sudo aptitude install libxml2-dev libxslt1-dev
pythonでsudoを付けたコマンドを実行する
パスワードをリダイレクトすればおk shell - Using sudo with Python script - Stack Overflow
import os
p = os.system('echo pass | sudo -S ...')
os.popen("sudo -S ...","w").write("pass")
django rest frameworkでBasic認証のあるサイトを扱う
basic認証のあるサイトでdjango rest frameworkを使ったjson apiみたいなのを作ろうと思った時に、認証してアクセスしても
{"detail": "Invalid username/password"}
みたいなメッセージが帰ってきてうまく情報を取って来れなかった。
# settings.py
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': ()
}
と認証を削除するといけた nginx - Django Rest Framework behind HTTP Basic Authentication - Stack Overflow
リストの文字列をリストに変換する
リクエストでリストの文字列をパラメーターにして送って、それをリストとして評価したかったので、調べてみた。
import ast
hoge = u'["A","B","C"]
fuga = ast.literal_eval(hoge)
32.2. ast — Abstract Syntax Trees — Python 2.7.10 documentation見ると
This can be used for safely evaluating strings containing Python values from untrusted sources without the need to parse the values oneself.
と、あるので、変換だけならチェックしなくても問題ない・・・かも?
参考:convert string representation of list to list in python - Stack Overflow
lxmlで が入った文章をxmlでパース出来ない
xmlに (空白)が入っている場合に、xmlとしてパースした場合に
lxml.etree.XMLSyntaxError: Entity 'nbsp' not defined
みたいなメッセージを出されちゃうことがある。解決策としては
- htmlとしてパースする
- xml定義をしっかりやっておく
- &の部分を適当に置換
くらいがある。
htmlとしてパース
from lxml import etree
from StringIO import StringIO
parser = etree.HTMLParser()
parsed = etree.HTML(StringIO(source), parser)
xml定義をしっかり書く
xmlとしてしっかり書いて、パーサーのパラメータとしてresolve_entities=Falseと指定すれば良いらしい
from lxml import etree
from StringIO import StringIO
source = """<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<hoge> fuga</hoge>"""
parser = etree.XMLParser(resolve_entities=False)
parsed = etree.parse(StringIO(source), parser)
print etree.tostring(parsed)
&を適当に置換
一個一個特殊文字をユニコードに変えるという手もあるけど、とても手間なので
source = source.replace('&','&')
とやってからパースすれば通る
except時にトレースバックを表示
import traceback
def hoge():
try:
...
except Exception as e:
traceback.print_exc()
こんな感じで、tracebackを使えば良い
参考:Python Exception Handling Techniques | Doug Hellmann
datetimeからタイムスタンプへの変換(逆も)
import datetime
import time
def datetime_to_timestamp(dt):
timestamp = time.mktime(dt.timetuple())
return timestamp
def timestamp_to_datetime(timestamp):
dt = datetime.datetime.fromtimestamp(timestamp)
return dt
こんな感じ
参考:pythonでdatetimeとtimestampを相互変換するコード - uokadaの見逃し三振は嫌いです
パイプで渡されたデータを受け取る
# encoding: UTF-8
import sys
lines = sys.stdin.readlines()
for line in lines:
print line
こんな感じ。ちょっとしたコマンド作る時に使えるのでメモ
参考;[Python]シェルからパイプで渡されたデータをPythonで受け取る « StudioT::DevLog
変数が文字列かチェックする
文字列が来てる場合はstrptimeやって、他の場合は普通に代入とかそんな場合に、文字列かチェックする必要があるのでメモ
hoge = "fuga"
if instanceof(hoge, basestring):
pass
こんな感じ。整数ならbasestringをintにするとかやればおk
formatにリストを渡す
l = ['hoge','fuga','hage']
print "{0},{1},{2}".format(tuple(l))
hoge,fuga,hage
こんな感じ。
forループ色々
dict
iteritemsを使う
if isinstance(d, dict):
for key, vakue in d.iteritems():
pass
listとかtuple
enumerateを使う。直接listの番号を取ってる訳じゃないけど
if isinstance(l, (list, tuple)):
for i, value in enumerate(l):
pass
object
if isinstance(o, type):
for key, value in vars(o).iteritems():
pass
psycopg2をインストールする
依存ライブラリとしてlibpg-devが必要。postgresql-server-dev-x.xが必要とか言われるけど、こっちで良い。
seleniumでchromiumを使う(Ubuntu 18.04)
Ubuntuではchromeでなく、chromiumを使うので、chromiumやってみる
pipでseleniumをインストール
pip install selenium
````
chromium、chromeドライバーをインストール
sudo aptitude -y install chromium-browser chromium-chromedriver
chromedriverをパスが通るところに移動(シンボリックリックを作る)
(webdriver.Chromeでパスを直接指定でも良いかもしれない(参考:[Using chromedriver with selenium/python/ubuntu](https://stackoverflow.com/questions/22476112/using-chromedriver-with-selenium-python-ubuntu))
sudo ln -s /usr/lib/chromium-browser/chromedriver /usr/bin/chromedriver
テストコード(参考;[SeleniumからHeadless Chromeを使ってみた](https://qiita.com/orangain/items/db4594113c04e8801aad))
```py
import time
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.chrome.options import Options
options = Options()
options.binary_location = '/usr/bin/chromium-browser'
options.add_argument('--headless')
driver = webdriver.Chrome(chrome_options=options)
driver.get('https://www.google.co.jp/')
assert 'Google' in driver.title
python 2.7でパラメータのurlエンコードで指定したハッシュの順番通りにする
普通にハッシュをパラメータに指定すると順番通りにいかないので一工夫必要
params = {'a':'a','b':'b','c':'c','d':'d'}
sorted_values = sorted(params.items(), key=lambda val: val[0])
urllib.urlencode(sorted_values)↲
これで
a=a&b=b&c=c&d=d
で出力される
python 2.7系をアップデートする
ソースをダウンロードしてmake
$ wget https://www.python.org/ftp/python/2.7.x/Python-2.7.x.tgz
$ tar -xvf Python-2.7.x.tgz
$ cd Python-2.7.x
$ ./configure --prefix=/path/to/install
$ make
$ sudo make install
参考:Ubuntu 14.04のPython2のデフォルトバージョンをPython 2.7.9にする
上書きしてアップデートする場合は、エラーが出たりするので、出たファイルを消したらいける