python 0埋め 削除する
datetime の日付0埋めを削除する方法については、検索したら解説が見つかります。
普通の文字列、例えば "0000120" を "120" にするにはどうすれば良いのだろう?
"python 0埋め 除去(削除、解除)" など色んなキーワードで検索したけどヒットしない。
除去する桁数が決まっていたら、format とか使えば出来るのかとか難しく考えていましたが。。
num = "0000120" print int(num)
試してみたら、これで除去してくれました。
常識なこと?であるため、検索してもヒットしなかったのかもしれません。
確かに、Java でもこんな感じでいけますしね。
正直、正攻法なのかは分かってません。
Integer.valueOf("0000120")
もし文字列 "120" にしたいのなら、str(int(num)) で。
ERROR: The node /hbase-unsecure is not in ZooKeeper.
エラー内容
Docker で HBase の Container を作っているのですが、hbase shell を起動した時に発生したエラー。
Docker とは何の関係もないエラーです。
ERROR: The node /hbase-unsecure is not in ZooKeeper. It should have been written by the master. Check the value configured in 'zookeeper.znode.parent'. There could be a mismatch with the one configured in the master.
HBase のMasterサーバー(HMaster)を起動すると、zookeeper 内に /hbase-unsecure が生成されるはずなのですが、それが作られていないよというエラー。
実際に、zkCli.sh で除いてみても、このノードは生成されていませんでした。
調査
HMaster が起動してないのかも?ということで、ログを見てみると以下のエラーが出て起動できていませんでした。
HMaster: Failed to become active master SIMPLE authentication is not enabled
このエラーは見た記憶がなかったのですが、以下に回答がありました。
https://stackoverflow.com/questions/35975094/master-hmaster-failed-to-become-active-master-simple-authentication-is-not-enab?rq=1
core-site.xml と hbase-site.xml で指定しているポート番号が一致していないだろうとのこと。
確認してみると、一致してませんでしたので、9000 で揃えました。
(HDP のドキュメント見ながら設定したはずなのに。。。)
core-site.xml
<property> <name>fs.defaultFS</name> <value>hdfs://hdp-resource.docker:9000</value> </property>
hbase-site.xml
<property> <name>hbase.rootdir</name> <value>hdfs://hdp-resource.docker:9000/apps/hbase/data</value> </property>
確認
改めて、HMaster を起動、RegionServer も起動してます。
/usr/hdp/current/hbase-master/bin/hbase-daemon.sh start master /usr/hdp/current/hbase-regionserver/bin/hbase-daemon.sh start regionserver
今度は hbase shell も問題なく動作しました。
hbase(main):001:0> list TABLE 0 row(s) in 0.5440 seconds => [] hbase(main):002:0> create_namespace 'ns' 0 row(s) in 0.0840 seconds hbase(main):003:0> list_namespace NAMESPACE default hbase ns 3 row(s) in 0.1300 seconds
色んなモジュールが連携していることもあって、設定ミスなど、はまりポイントが多いです。
Unity Unable to list target platforms
Unity で作成したゲームを Android の実機にビルドしようとしたら、以下のエラーが発生。
Unable to list target platforms.
コンソールには以下のエラーが表示されているが、意味が分からない。
確かにしばらく Unity を触っていなかったけど、以前は問題なくビルドできていた。
メッセージが言うとおり、Android SDKのパスを確認してみたけど問題なさそう。
Unity 側
調べてみると、どうやら Android Studio のアップデートによる影響らしい。
https://answers.unity.com/questions/1320634/unable-to-list-target-platforms-when-i-try-to-buil.html
記事のとおり、tools フォルダ毎入れ替えたらビルドが通るようになりました。
そういえば、kotlin でアプリを作る時に、Android Studio のアップデートをしたような気がします。
となると、今度は kotlin のプログラミングが上手く動作しなくなっているかも。。
開発環境に依存関係を持たせたくないので、VM などして、開発環境を分けた方がいいかもしれない。
JMockito 一部のメソッドのみをモック化する(Java モック)
これの JMockito 版です。
blueskyarea.hatenablog.com
モック化するクラス
public class PointCard { public PointCard() { } public String getMemberName() { return "hoge"; } public long getPoint() { return 1000L; } }
テスト対象のクラス
public class Member { private PointCard pointCard; public Member() { this.pointCard = new PointCard(); } public String getMemberNameAndPoint() { return pointCard.getMemberName() + "_" + pointCard.getPoint(); } }
テスト
@RunWith(JMockit.class) public class MemberTest { @Test public void testGetPointIsMocked() { new NonStrictExpectations(PointCard.class) { // 1 { new PointCard().getPoint(); // 2 result = 7777L; // 3 } }; Member member = new Member(); assertThat(member.getMemberNameAndPoint(), is("hoge_7777")); // 4 } }
1. Expectations(NonStrictExpectations) のコンストラクタに、モック化するクラスの Class オブジェクトを渡す。
2. モック化したいメソッドを記述する。
3. そのモックの振る舞いを記述する。
4. 結果を評価する。
今回、PointCard クラスのメソッドにおいて、
getMemberName() はモック化していないため、"hoge" がそのまま返却される。
getPoint() はモック化していて、7777 を返却するように定義しているため、7777 が返却される。
よって結果は、"hoge_7777" となる。
これをもし、以下のように書いた場合、
@RunWith(JMockit.class) public class MemberTest { @Test public void testGetPointIsMocked(@Mocked PointCard pointCard) { new NonStrictExpectations() { { pointCard.getPoint(); result = 7777L; } }; Member member = new Member(); assertThat(member.getMemberNameAndPoint(), is("hoge_7777")); } }
getMemberName() もモック化されてしまう。
そして振る舞いを定義していないので、null が返却される。
よって結果は、"null_7777" となる。
所感
Mockito で同じことを実現したいときは、@Spy や @InjectMocks を定義してあげる必要がありました。
JMockito では特別なアノテーションも必要ないので、これに関しては、JMockito の方がシンプルに書けて良いなと思います。
JMockito 引数に応じて返す値を変化させる(Java モック)
これの JMockito 版です。
blueskyarea.hatenablog.com
テストコード(JUnit)
@RunWith(JMockit.class) public class BirthMonthTest { // Without mock @Test public void testGetBirthStoneWithoutMock() { BirthMonth birthMonth = new BirthMonth(2); assertThat(birthMonth.getBirthStone(2), is(nullValue())); assertThat(birthMonth.getBirthStone(7), is(nullValue())); assertThat(birthMonth.getBirthStone(11), is(nullValue())); } // With mock @Test public void testGetBirthStoneWithMock(@Mocked BirthMonth birthMonth) { new NonStrictExpectations() { { birthMonth.getBirthStone(2); result = "amethyst"; birthMonth.getBirthStone(7); result = "ruby"; birthMonth.getBirthStone(11); result = "topaz"; birthMonth.getBirthStone(anyInt); result = "not found"; } }; // exception if not "NonStrictExpectations". assertThat(birthMonth.getBirthStone(5), is("not found")); assertThat(birthMonth.getBirthStone(2), is("amethyst")); assertThat(birthMonth.getBirthStone(7), is("ruby")); assertThat(birthMonth.getBirthStone(11), is("topaz")); assertThat(birthMonth.getBirthStone(20), is("not found")); // exception if not "NonStrictExpectations". assertThat(birthMonth.getBirthStone(30), is("not found")); } }
Expectations を使用した場合、定義した振る舞いの順番どおりに、そのメソッドが呼ばれることが期待される。
この例では、まず最初に 2 が引数として与えられた場合の振る舞いが定義されている。
ただ、assertThat では最初に 5 が引数として与えられることになっているため、この時点でエラーになる(expect 2, but 5)。
また、最後の assertThat では 30 を引数として与えているが、定義した振る舞いの anyInt は、その前の引数 20 に対して適用されるため(使用済みのような扱い)、30 の場合の振る舞いが定義していないということでエラーになる。
いずれの場合も以下のエラー。
UnexpectedInvocation: Unexpected invocation of:
NonStrictExpectations を使用してあげることで、この辺りの制約がゆるくなり、定義した振る舞いの数が呼び出しの数よりも少なかったとしても、anyInt で定義した振る舞いが適用されるか、もし anyInt を定義していなければ、null(初期値) が返却されるような動作になる。
機能的には問題ないと思うのですが、この辺りについては Mockito の方が若干分かり易い(書き方)気がします。
Mockito の場合。
when(birthMonth.getBirthStone(2)).thenReturn("amethyst");
JMockito でも、無理やり一行で書けますが。。
birthMonth.getBirthStone(2); result = "amethyst";
JMockito あるメソッドが任意の値を返す(Java モック)
これの JMockito 版です。
blueskyarea.hatenablog.com
Mockito 版の記事と同じクラスをテスト対象にしました。
テストコード(JUnit)
import mockit.Expectations; import mockit.Mocked; import mockit.integration.junit4.JMockit; @RunWith(JMockit.class) public class MemberTest { // Without mock @Test public void testGetMemberInfoWithoutMock() { Member member = new Member(1, "hoge"); assertThat(member.getPointCard().getPoint(), is(1000L)); } // With Mock @Test public void testGetMemberInfoWithMock(@Mocked Member member) { PointCard pointCard = new PointCard(1, "hoge", 2000L); new Expectations() { { member.getPointCard(); result = pointCard; } }; assertThat(member.getPointCard(), is(pointCard)); assertThat(pointCard.getPoint(), is(2000L)); } }
@RunWith(JMockit.class) アノテーションを付けないと、エラーで怒られました。
java.lang.IllegalStateException: JMockit wasn't properly initialized; check that jmockit.jar precedes junit.jar in the classpath (if using JUnit; if not, check the documentation)
classpath 内において、jmockit.jar を junit.jar よりも先に定義しておく必要があるみたいです。
自分の環境下で上手く出来なかったため、代わりにこのアノテーションで回避してます。
結果
Mockito と同様のモックを生成することが出来ました。
Mockito では期待する動作を when().thenReturn() で定義していましたが、JMockito では Expectations で定義します。
この程度の内容であれば Mockito とどちらが使いやすいか検討するまでの違いは見当たりません。
Mockito と JMockito 名前は非常に似ていますが、モックの書き方は全く異なるので、プロジェクト単位でどちらかを使うかは決めた方が良さそうです。
「モックの作り方」についてネットの検索結果をそのまま適用していると、いつの間にか混在しているみたいなこともありそうです。
python bash のコマンドを実行
調べてみると色んなやり方が見つかりましたが、自分にとって一番シンプルだったやり方を。
import subprocess bashCommand = "ls -alt" output = subprocess.Popen(bashCommand, stdout=subprocess.PIPE, shell=True).communicate()[0] print(output)
コマンドの意味とか
subprocess.Popen
新しいプロセスで子のプログラムを実行してくれる。
stdout=subprocess.PIPE
標準出力をパイプする。コンソールに表示させない。
communicate() はタプル (stdoutdata, stderrdata) を返す。
戻り値のタプルから None ではない値を取得するためには、 stdout=PIPE または stderr=PIPE を指定しなければならない。
shell=True
shell が True なら、指定されたコマンドはシェルによって実行される。
Popen.communicate(input)
プロセスと通信する。
end-of-file に到達するまでデータを stdin に送信し、stdout および stderr からデータを受信する。
オプション引数 input には子プロセスに送られる文字列か、あるいはデータを送らない場合は None を指定する。
受信したデータはメモリにバッファされるため、返されるデータが大きい場合はこのメソッドを使うべきではない。
結果
$ ls -alt 合計 12 drwxrwxr-x 2 xx xx 4096 6月 25 23:18 . -rw-rw-r-- 1 xx xx 339 6月 25 23:18 execBashCommand.py drwxrwxr-x 9 xx xx 4096 6月 25 22:40 ..
$ python execBashCommand.py 合計 12 drwxrwxr-x 2 xx xx 4096 6月 25 23:22 . -rw-rw-r-- 1 xx xx 309 6月 25 23:22 execBashCommand.py drwxrwxr-x 9 xx xx 4096 6月 25 22:40 ..
普通に bash で実行したコマンドと同じ結果が得られた。
今回、stdout が欲しいから、communicate()[0] としている。
もし、communicate()[1] とした場合
$ python execBashCommand.py None
stderr の値が(実際には存在しないから None)が出力されている。