rosのCMakeListsのお勉強
T・B・D
install
install(DIRECTORY launch/ DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}/launch FILES_MATCHING PATTERN "*.launch" )
- .launchだけをコピー
install(DIRECTORY launch/ DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}/launch PATTERN ".svn" EXCLUDE)
- .svnを除き、それ以外をコピー
mockテストのお勉強
mock.return_value
- 返り値を指定できる
mock.called
mock.call_count
- 何回呼ばれたか確認できる
mock.call_args
mock.call_args_list
- 引数のリストがわかる
mock.side_effect
- いろんなものが指定できる
例えば(イテレート)
side_effect = chain([1,2,3,4])
mock.method_calls
mock.mock_calls
- mock_calls は、メソッド,特殊メソッド,戻り値のモックまで、モックオブジェクトに対するすべての呼び出しを記録する
mock.assert_called
mock.assert_called_once
mock.assert_called_with
mock.assert_called_once_with
mock.assert_any_call
assert_has_calls
参考:
26.5. unittest.mock — モックオブジェクトライブラリ — Python 3.6.1 ドキュメント
パッチデコレータ
@patch
参考:
Pythonのテストコードでmockを使ってみた | Developers.IO
mock(Pyhtonモックライブラリ)についてのメモ - Qiita
Pythonで学ぶ 基礎からのプログラミング入門 (34) Pythonのテスト手法 | マイナビニュース
ユニットテスト
# @raises 例外のテスト @raises(Error) def test_invalid_arg(): actual = add(None, 1)
参考:
rospyのお勉強
rospy.get_param
- パラメータサーバーから値をとってくる
rospy.get_param(param_name, default)
参考: rospy/Overview/Parameter Server - ROS Wiki
rospy.Time
- rate,sleep,durationなどよく使うものが多い
- rospy.Timer(period, callback, oneshot=False)
- periodで指定した周期で定期的にcallbackが呼ばれる
参考:
rospy/Overview/Time - ROS Wiki
rospy.wait_for_message(topic, topic_type, timeout)
- トピックを一回だけサブする関数
rospy.ROSInterruptException
- KeyboardInterruptなどInterruptの操作のException
Pythonのお勉強(1)
- with文
- ラムダ式
- 引数
- イテレータ
- ジェネレータ
- デコレータ
- スコープ
- クロージャ
- クラス継承
- クラス属性とインスタンス属性
- スタティックメソッド
- クラスメソッド
- プライベートメンバ
- Linuxコマンドを呼ぶ
- 入出力
- ソケット通信
- スレッド
- その他
- スクリプト言語とコンパイル言語の違い
- lint
- *args **kwargs
- glob
with文
コンテキストマネージャとして利用して、動作を制御することができる。(enterメソッド、exitメソッド)
以下の場合、writeメソッドの後、必ずファイルrobot.txtが閉じられる。
with open('robot.txt', 'r', encoding = 'utf8') as f: all_text = f.read() print(all_text)
以下のように書くと、エラー処理などでファイルが閉じられない可能性があるため、上記のように書くことを推奨。
f = open('robot.txt', 'r', encoding = 'utf8') for line in f: print(line , end='') f.close()
ラムダ式
lambda 引数:命令
is_even = lambda x: x % 2 == 0 is_even(2) -> True
引数
可変引数
- *のときタプルになる
>>> def func(*hoge): ... print hoge ... >>> func("1","2","3") ('1', '2', '3')
- **のとき辞書型になる
>>> def func(**hoge): ... print hoge ... >>> func(a=1,b=2,c=3) {'a': 1, 'c': 3, 'b': 2} >>>
イテレータ
参考;
10.1. itertools — 効率的なループ実行のためのイテレータ生成関数 — Python 3.6.5 ドキュメント
ジェネレータ
イテレータの一種
def robot_num(m): print("%d robot num" % m) while m < 5: if m == 4: print("m=4") yield m m += 1 print("stop product robot") return
実行結果
In [2]: cnt = robot_num(2) In [3]: next(cnt) 2 robot num Out[3]: 2 In [4]: next(cnt) Out[4]: 3 In [5]: next(cnt) m=4 Out[5]: 4 In [6]: next(cnt) stop product robot --------------------------------------------------------------------------- StopIteration Traceback (most recent call last) <ipython-input-6-77509b5792d1> in <module>() ----> 1 next(cnt) StopIteration:
デコレータ
関数やクラスの機能変更、拡張を行うための機構
@robot_log def calc_add(robot1,robot2): return robot1+robot2
は以下と同じ
def calc_add(robot1,robot2): return robot1+robot2 calc_add = robot_log(calc_add)
ここで、robot_logを正しく作ると、この関数を呼ぶとlogをとるような機能を追加できる
スコープ
参考:RubyプログラマがPythonを学び始めて知ったこと10選 ④ - donghai821の日記
pythonにprivate変数がない件:千里の道も一歩から:So-netブログ
Python - Pythonの変数やメソッドの命名について(アンダーバー)(41277)|teratail
クロージャ
参考:Python Tips: Python でクロージャを使いたい - Life with Python
クラス継承
参考:
Python の super() 関数の使い方 - Life with Python
クラス属性とインスタンス属性
大事な考え方。要復習。クラスと名前空間と関連付けて整理しよう。
参考:Pythonでのクラス属性とインスタンス属性 - gogochephy’s diary
スタティックメソッド
以下のようにインスタンスに作用しないメソッド
class robot_calc(object): @staticmethod def robot_add(x,y): #selfがない return x+y a = robot_calc.robot_add(1,2)
クラスメソッド
インスタンスではなくクラスそのものに作用するメソッド
class RoboVar: ene = 1 @classmethod def full(cls, power): return cls.ene * power class FullPower(RoboVar): ene = 2 x = FullPower.full(3) # RoboVar.full(FullPower,3)
プライベートメンバ
- アンダースコアひとつ _robot → クラス内部だけで利用する
- アンダースコアふたつ __robot → クラス外部から参照できなくなる(厳密には_<クラス名>__<属性名>とすればアクセスできるがより安全)
Linuxコマンドを呼ぶ
#!/usr/bin/env python import subprocess p_test = subprocess.check_call(['ls','-a'])
参考: pythonでLinuxコマンドを実行する - ihit's diary
入出力
csv
import csv with open('robodata.csv','r',encoding='utf8') as f: robodata = [k for k in csv.reader(f)] with open('roboout.csv','w',newline='') as f: writer = csv.writer(f) writer.writerows(robodata)
pickle
以下のようにすることでオブジェクトの保存ができる
import pickle mydata = [1,2,3] with open('pickle_test.pickle','wb') as f: #バイナリ形式で開くこと pickle.dump(mydata,f) with open('pickle_test.pickle','rb') as f: pic_data = pickle.load(f)
複数のオブジェクトを保存するときは以下のように記述
import pickle import numpy as np robo1 = np.float(28.0) robo2 = np.array([[1.0,2.0],[3.0,4.0]]) robo3 = {'tetsujin':21, 'atom':'1000000'} with open('pickle_test2.pickle','wb') as f: #バイナリ形式で開くこと pickle.dump([robo1,robo2,robo3],f) with open('pickle_test2.pickle','rb') as f: [r1,r2,r3] = pickle.load(f) print(r3['tetsujin'])
ソケット通信
- connect : サーバーに接続
- send : データ送信
- sendall : すべて送りきるまで終わらない
- settimeout : タイムアウト値を設定する
- recv : データ受信
- socket.timeout : exception OSErrorのサブクラス
- socket.error : exception OSErrorの非推奨のエイリアス
参考:
スレッド
参考:
その他
- struct.pack("i",data) : int型でdataをパックする
- unicode() : unicodeへ変換
- .split() : 単語を分割してリストへ
- ~[-1] : リストの最後のもの
- ~[0:-1] : リストの最初から最後から一つ手前まで
- .append : リストの最後に追加
- time.sleep : ~s待つ
- .first()
- .join() : 連結して一つの文字にする
- .items() : 辞書をリストに変換
- continue : 現在のループを終了して次のループへ
参考:
http://www.yukun.info/blog/2008/09/python-file-write-writelines.html
python - What is the difference between .one() and .first() - Stack Overflow
キーと値のリストを取得(keysメソッド, valuesメソッド, itemsメソッド) - 辞書 - Python入門
Pythonのコードをきれいに書くためのTips | TRIVIAL TECHNOLOGIES 4 @ats のイクメン日記
スクリプト言語とコンパイル言語の違い
参考:
lint
*args **kwargs
glob
rosテストのお勉強(python)
unittest
CMakeLists.txt
catkin_python_setup() if(CATKIN_ENABLE_TESTING) find_package(rostest REQUIRED) add_rostest(test/mytest.test) endif()
package.xml
<test_depend>rostest</test_depend> <test_depend>python-nose</test_depend>
↑テストにnoseをつかう場合
mytest.test
<launch> <node pkg="mypkg" type="mynode" name="mynode" /> <test test-name="test_mynode" pkg="mypkg" type="test_mynode.py" /> </launch>
test_mynode.py
#!/usr/bin/env python from nose.tools import eq_, raises import unittest import rostest, rospy from mypkg.mytest import MyTest class TestMyTest(unittest.TestCase): def setUp(self): pass @raises(rospy.ROSException) def test_mytest1(self): instance = MyTest() def test_mytest2(self): eq_(10 / 5, 2) if __name__ == '__main__': rospy.init_node('test_sample') rostest.rosrun('mypkg', 'test_sample', TestMyTest)
実行
$rostest test_rospy/test/mytest.test
setup.py
#!/usr/bin/env python from distutils.core import setup from catkin_pkg.python_setup import generate_distutils_setup setup_args = generate_distutils_setup( packages=['rostest'], package_dir={'': 'src'}, ) setup(**setup_args)
rostest-test.test
<launch> <test test-name="test_rostest" pkg="rostest" type="test_rostest.py" /> </launch>
ディレクトリ構成
参考:
ja/rospy_tutorials/Tutorials/Makefile - ROS Wiki
2. setup スクリプトを書く — Python 3.6.5 ドキュメント
参考:
ROS勉強記録: catkinでのpythonのtestについて
ROS C++コード用テストライブラリgtestの使い方(日本語訳) - MyEnigma
rostest - Minimum Working Example - ROS Answers: Open Source Q&A Forum
noseで気軽にテストを書く(+geventの場合) - Qiita
pythonのテストを書いてみる
unittest
Robot and Animal
roboani.py
class Robot: def get_name(self): return "robot" def get_legs(self): return 2 class Animal: def get_name(self): return "animal" def get_legs(self): return 4 def calc_roboani_legs(robot,animal,heads,legs): robo_l = robot.get_legs() ani_l = animal.get_legs() robot_name = robot.get_name() animal_name = animal.get_name() animal_num = (legs - (robo_l*heads)) // (ani_l-robo_l) robot_num = heads - animal_num print "------" print "head",heads,"leg",legs print robot_num,animal_num return robot_num,animal_num if __name__ == '__main__': calc_roboani_legs(Robot(),Animal(),heads=10,legs=28)
Test
test_roboani.py
import unittest, roboani class TestRobotAnimal(unittest.TestCase): def setUp(self): self.robot = roboani.Robot() self.animal = roboani.Animal() def tearDown(self): pass def test_legs(self): self.assertEqual(self.robot.get_legs(),2,"leg num") self.assertEqual(self.animal.get_legs(),4,"leg num") def test_roboani(self): robot, animal = roboani.calc_roboani_legs( self.robot,self.animal, heads = 10, legs = 28) self.assertEqual((robot,animal) ,(6,4), "robot animal calc")
テスト実行
$ python -m unittest test_roboani
- -m
: モジュールをスクリプトとして実行
結果
.------ head 10 leg 28 6 4 . ---------------------------------------------------------------------- Ran 2 tests in 0.000s OK
mocktest
RobotDataBaseConnect
# -*- coding:utf-8 -*- import unittest from mock import Mock, patch class DataBaseConnect(object): def __init__(self): pass def find(self, param): print('find ' + param) class CalculationMovement(object): def __init__(self, data): self.__dataget = data def execute(self): return self.__dataget.find('param') calc = CalculationMovement(DataBaseConnect()) calc.execute() # ---------------- mock test --------------------------# class CalculationModelTestCase(unittest.TestCase): def setUp(self): pass def tearDown(self): pass def test_execute_1(self): mock_test = Mock() mock_test.find.return_value = 'mock_test' test_obj = CalculationMovement(mock_test) self.assertEqual('mock_test', test_obj.execute()) self.assertEqual(mock_test.find.call_count, 1) self.assertEqual(list(mock_test.find.call_args_list[0]), [('param',),{}]) def test_execute_2(self): DataBaseConnect.find = Mock(return_value='mock_test') mock_test = DataBaseConnect() test_obj = CalculationMovement(mock_test) self.assertEqual('mock_test', test_obj.execute()) def test_execute_3(self): with patch('__main__.DataBaseConnect') as mock_test: mock_test.find.return_value = 'with_mock_test' test_obj = CalculationMovement(mock_test) self.assertEqual('with_mock_test', test_obj.execute()) unittest.main()
結果
find param ... ---------------------------------------------------------------------- Ran 3 tests in 0.002s OK
参考:
PythonでMockを使ったユニットテスト - 工作とかプログラミングとか
python - How to unittest that a thread is spawned? - Stack Overflow
サンプルでみる Python の Mock ライブラリ Mox の使い方 | CUBE SUGAR STORAGE
EasyMockでSocketクラスのモックを作る - Yのはてな
Pythonのテストコードでmockを使ってみた | DevelopersIO
Pythonのコードをきれいに書くためのTips | TRIVIAL TECHNOLOGIES 4 @ats のイクメン日記
http://momijiame.tumblr.com/post/22379282563/モックオブジェクトフレームワーク-pymox-を使って-python-のテストを書く
標準ライブラリのunittestで例外の発生を確認するテスト - podhmoの日記
unit testing - How do you test that a Python function throws an exception? - Stack Overflow