landrunner’s blog

しばらく開発から離れてた人間が、技術的キャッチアップを図るための勉強ブログ

PandasのDataFrameからCSV形式の文字列を生成する

PandasのDataFrameからCSVにする方法を検索すると、ファイルに書き込む方法しかでてこなかったのでメモ程度にあげておきます。

内部に保持しているDataFrameの内容をCSVとして他のマシンに送るだけで、わざわざ一度ファイルに書き込む必要はなかったのですが、 CSVは意外と厄介な仕様をしており、自前で変換コードを書くのは避けたかったのです。

やり方

import pandas as pd
import numpy as np

df = pd.DataFrame(np.arange(18).reshape(6, 3))
csv_string = df.to_csv()
print(csv_string)

ポイントはto_csv()の引数path_or_bufにファイル名を割り当てないことです。

これでCSVに変換された結果がstringとして返ってきます。

以上

VSCode Remote developmentを使ってProxy下にあるマシンからクラウド上のサーバで開発できるようにする

想定環境

想定環境としてはこんな感じで、Windowsのクライアント上にあるVS Codeからクラウド上のサーバへRemote Developmentののため接続をします。

VSCodeはクライアントにインストールされたsshコマンドを利用してサーバへ接続します。

ここで問題になるのが以下の点です。

  • そもそもProxyは外部の22番ポートへのアクセスを認めていないことが多い
  • 素のsshコマンドは単独でProxy経由での接続機能がなく、Proxy接続を行うためのconnectコマンドはwindows版が提供されていない
  • プロキシ経由での接続を行えるPuttyTeraTermVSCodeでは使えない

2つ目と3つ目はどっちか1つ解決できればいいです。

今回は2つ目の方をターゲットにやっていきましょう。

ssh待ち受けポートの変更

22番ポートへのアクセスを認めてくれない問題はサーバ側の待ち受けポートを443番ポートに変更して対処します。

一旦サーバへログインして以下の通り設定を書き換えましょう。

$ sudo echo "Port 443" >> /etc/ssh/sshd_config
$ sudo systemctl restart ssh

443はhttpsのポートなので大抵の場合うまくいきます。

入りたいサーバのsshポートが書き換えられない場合、クラウド側に踏み台サーバを用意するなど、いくつかやり方はあると思います。

connectコマンドのインストール

インストール方法はざっと調べたところざっと3通り。

  1. ソースコードを探し、windows環境下でコンパイル
  2. CygwinMinGWを入れてconnect-proxyをインストール
  3. その他、connectコマンドが含まれているソフトをインストール

1はソースコードを探すのがちょっと面倒なのと、そのままコンパイルできるか不明なのでパス。

2はWSLがある今、CygwinMinGWを必要とすることもそうありません。 connectコマンドのためだけに入れるのはちょっと避けたいところです。

というわけで消去法的に3なのですが、なんとGit for windowsをインストールしたら入っていました。

https://gitforwindows.org/

MinGWコンパイルされたやつなので結局2と同じではあるのですが、Gitなら入れておいても使う機会はあるでしょう。

というわけでこれを使いましょう。

パスを通すと他と重複する可能性があるので、とりあえずフルパスで使うことにします。

.ssh/configの編集

Windowsクライアントから以下のコマンドを打つとsshのconfigファイルが開きます。

> code $HOME/.ssh/config

これを次のように編集します。

Host ubuntu-cloud 
  HostName <ubuntu-cloud-ip-address>
  Port 443
  User ubuntu
  IdentityFile ~/.ssh/id_rsa
  ProxyCommand C:\Program Files\Git\mingw64\bin\connect.exe <proxy-hostname>:<proxy-port> %h %p
  ForwardAgent yes

ここで、<ubuntu-cloud-ip-address>, <proxy-hostname>, <proxxy-port>は環境に合わせて書きなおしてください。

VSCodeからのRemote Development機能の利用

vscodeからリモート接続を選択すると、設定ファイルに設定したホストが表示されています。

ここで+を押してクラウド上のサーバにつながれば成功です。

SSHで公開鍵認証を設定して、Puttyでログインできるようにする

新しいサーバを立てる度に、やり方を調べているのでメモ程度に。

キーペアの生成

今回はPowershellから。

> ssh-keygen.exe -t rsa -b 4096
Generating public/private rsa key pair.
Enter file in which to save the key (C:\Users\xxxx/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in C:\Users\xxxx/.ssh/id_rsa.
Your public key has been saved in C:\Users\xxxx/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:+40z7lDAdafKEAon8rFIXpJfD60auDVk/Q1BrcpVo40 
The key's randomart image is:
+---[RSA 4096]----+
+----[SHA256]-----+

公開鍵サーバへコピー

> scp .ssh/id_ras.pub xxxx@192.168.34.9:~/.ssh/authorized_keys

一旦普通にサーバにログインして.sshの権限を変更。

$ sudo chmod 700 .ssh -R

戻って公開鍵でログインできるか調べる。 成功したらsshの設定はとりあえず完了。

> ssh -i id_rsa 192.168.34.9 

秘密鍵puttyのものに変換

puttygenを起動し、~/.ssh/id_rsaファイルを開く。

f:id:landrunner:20200510170837p:plain
puttygen

こんな感じで開けたらppk形式で保存する。

Puttyで開く

さっき生成したppkファイルを秘密鍵に指定して普通に開く。 f:id:landrunner:20200512231113p:plain

ちなみにPuttyを使うのはプロキシ経由でのSSHができるから。

人によってはすごく便利。

iframe, frameの中から親windowのどの要素に表示されているかを取得する

この記事はQiitaの記事をエクスポートしたものです。内容が古くなっている可能性があります。

そんなに使うこともないだろうけど、調べるのに意外とてこずったので自分用にメモ。 window.frameElementに親ウインドウのframe, iframeの要素が含まれている。 frameとして表示されていない場合はこの値はnullになる。

<!DOCTYPE html>
<html>
    <body>
        <iframe id='frame_sample' src='frame.html'>
             iframe対応ブラウザでみてください
        </iframe>
    </body>
</html>
<!DOCTYPE html>
<html>
    <body>
       <script>
          if(window.frameElement != null){
              document.write(window.frameElement.id + "内で表示されています。");
           }else{
              document.write("frameとして表示されていません。");
           }
       </script>
    </body>
</html>

表示内容: f:id:landrunner:20200412153212p:plain

注)多分cross originでは使えないと思う。

Javaのプリミティブ型配列操作(結合・部分配列・サイズ変更)

プリミティブ型配列

Javaではプリミティブ型(intとかbyteとか)はオブジェクトではないためジェネリクスに適用できないので、Collection等で使えない。 なのでプリミティブ型の値の集合は配列として扱うことになりやすいけど、プリイティブ型の配列はかなり扱いづらい。 オートボクシングが使えないとか、可変長配列(Listとか)にできないなどデメリットがいっぱいだ。

int a = 0;
Integer wa = a; //OK
int[] b = {0};
Integer[] wb = b; //コンパイルエラー オートボクシングはきかない
List<Integer> lb = Arrays.asList(b); //コンパイルエラー int[]のListが生成されそうになる

今回はそれでも配列を使わないといけない時のために結合等の操作方法をまとめておく。 ちなみにここで述べる方法はオブジェクト型の配列にも使用できるものが多いけど、よほど問題がない限り一度Listにしてから操作したほうがいいと思う。 なお、ここのコードはJava7以上の環境を想定している。

配列の結合

標準機能の利用

System.arraycopyを使う。 引数が5つもありどれに何を入れればいいかわかりにくい。バグの温床になりそう。 一応使い方を説明すると コピー元配列、コピー元配列の開始位置、コピー先配列、コピー先配列開始位置、コピーする要素数の順で入力する。

byte[] a = {0,1,2}; 
byte[] b = {3,4,5};
byte[] c = new byte[a.length + b.length];
System.arraycopy(a,0,c,0,a.length); //a→cにコピー
System.arraycopy(b,0,c,a.length, b.length); //b→cにコピー
System.out.println(Arrays.toString(c)); //[0,1,2,3,4,5]が表示される

apache commons langの利用

Apache Commons Langに含まれるArrayUtils.addAllを使えば簡単に書ける。 ちなみにこのメソッドの中では、上のSystem.arraycopyを呼び出している。

byte[] a = {0,1,2}; 
byte[] b = {3,4,5};
//aの後ろにbのすべての要素を追加した配列を返す
byte[] c = ArrayUtils.addAll(a,b); 
System.out.println(Arrays.toString(c)); //[0,1,2,3,4,5]が表示される

guavaの利用

google guavaのBytes.concatでもArrayUtilsと同じようなことができる。 これも中では同じようにSystem.arraycopyを呼んでいる。 こちらのメリットは複数の配列を同時に結合できること。 まとめて複数個の配列を結合するのであれば、一度に領域を確保できる分ArrayUtils.addAllより速い。

byte[] a = {0,1,2}; 
byte[] b = {3,4,5};
byte[] c = {6};
//guavaのBytes.concatでa,b,cの配列をまとめて結合
byte[] d = Bytes.concat(a,b,c); 
System.out.println(Arrays.toString(d)); //[0,1,2,3,4,5,6]が表示される

guavaでbyte以外のプリミティブ型の結合を行う場合は、対応するクラスのconcatを使う。 対応は byte→Bytes int→Ints double→Doubles みたいな感じで先頭を大文字にしてお尻にsをつけたやつ。

部分配列の取得

Arrays.copyOfRangeを使用する。 こいつの仕様が少し厄介で、copyOfRange(byte[] original, int from, int to)という形で範囲を指定するのだけど、toのindexの要素はコピーされず、そのひとつ前の要素までがコピーされる。

byte[] a = {0,1,2,3,4,5};
byte[] b = Arrays.copyOfRange(a,2,4); //a[2]:2, a[3]:3,a[4]:4 
System.out.println(Arrays.toString(b)); //[2,3]が表示される。

最初の要素からのコピーであれば下で書いているcopyOfも使用できる。

配列のサイズ変更

といっても新しい配列を作って元の配列の内容をコピーするだけなんだけど。 Arrays.copyOfを使用すれば、長くも短くもできる。

byte[] a = {0,1,2};
byte[] b = Arrays.copyOf(a, 4); //要素4の配列を生成
byte[] c = Arrays.copyOf(a, 2); //要素2の配列を生成
System.out.println("Length:" + a.length + " Elem:" + Arrays.toString(a));
//Length:3 Elem:[0,1,2]
System.out.println("Length:" + b.length + " Elem:" + Arrays.toString(b));
//Length:4 Elem:[0,1,2,0]
System.out.println("Length:" + c.length + " Elem:" + Arrays.toString(c));
//Length:2 Elem:[0,1]

おわりに

配列で困ったらとりあずArrays, Commons Lang, Guavaあたりを見てみよう。 今回書いたこと以外にもソートだったり値のサーチだったりそれなりのことはできる。

JavaScriptで先に処理を実行できるようイベントリスナを登録する

この記事はQiitaの記事をエクスポートしたものです。内容が古くなっている可能性があります。

おことわり

3年前に書いたこの記事ですが、未だにいいねをしてくれる人がいて光栄です。 ただ、この記事で書かれてる内容はあくまで既存JavaScriptが変更できない時のための応急処置用です。 クライアントサイドのパフォーマンスに思いっきり影響するのであまり多用しないようにしてください。 以上 2019/2/26追記

前書き

JavaScriptで何かイベントがあった時に、すでに登録されているイベントリスナより先に処理を実行する方法を考えた。普通はイベントリスナの登録順を書き換えて実行順をいじればいいんだけど、それができない場合もあるため。

やり方

以下のコードを参照。 この例ではbutton要素が押された時に、buttonに登録されたイベントリスナが実行される前にalertが発生する。

function cap_event(e){
    if(�$(e.target).is("button")){ //ここで要素を指定
        //実行したい処理を書く
        alert("button " + e.target.id + " clicked");
    }
}
window.addEventListener('click',cap_event,true);

ターゲットの指定がやりやすいのでjQueryを利用している。jQueryはなくてもできる。

ポイントはwindowに対してイベントリスナを登録しているところと、登録時に3番目の引数(useCapture)をtrueにしているところ。 参考: http://qiita.com/tkengo/items/39a9ecd426e53d6bd513

理屈

なぜこれで処理が最初に実行されるかという話だけど、JavaScriptにおけるイベントの伝搬順を利用してる。 JavaScriptでは、キャプチャフェーズ→ターゲットフェーズ→バブリングフェーズの順でイベントリスナ実行される。(図はW3Cの�サイトから引用) image

onclickなんかは基本的にターゲットフェーズ・バブリングフェーズで実行されるようで、キャプチャフェーズに実行するようイベントリスナを登録(useCaptureをtrueに設定)すればその処理は先に実行される。

しかし、ターゲットとなる要素に対しては、ターゲットフェーズの処理しか起きないっぽい(この辺はもしかしたらブラウザの仕様によるかも)。以下のコードのようにターゲット要素に対してキャプチャフェーズにイベントリスナを設定しても、先に別のイベントリスナを登録していたら、それが先に実行される。

var b = document.getElementById('bid');
b.addEventListener('click',process1); 
b.addEventListener('click',process2,true); //キャプチャフェーズのイベント
//button bid をクリックするとprocess1→process2の順で実行される

そこで今回のやり方ではwindowのキャプチャフェーズで、ターゲットを判別して先に実行させたい処理を実行させている。windowのキャプチャフェーズには一番最初にイベントが伝搬するので、一番最初に実行される。

function cap_event(e){
    if(�$(e.target).is("#bid")){
        alert("button " + e.target.id + " clicked");
    }
}
window.addEventListener('click',cap_event,true);

参考: http://www.w3.org/TR/DOM-Level-3-Events/ http://qiita.com/hosomichi/items/49500fea5fdf43f59c58

「みずほ銀行システム統合、苦闘の19年史」を読んだ

概要

Amazonの公式サイトより引用。

みずほフィナンシャルグループ(FG)が2011年から進めてきた「勘定系システム」の刷新・統合プロジェクトが2019年7月、ついに完了した。

富士通日立製作所日本IBMNTTデータを筆頭に1000社ものシステムインテグレーターが参加したものの、2度にわたって開発完了が延期になったことから、なかなか完成しないスペイン・バルセロナの教会にちなんで「IT業界のサグラダファミリア」とまで呼ばれた史上最大級のITプロジェクトだ。

みずほFGは完了までに8年もの年月と、35万人月、4000億円台半ばをつぎ込んだ。

1980年代に稼働した「第3次オンラインシステム」の全面刷新は、第一勧業銀行、富士銀行、日本興業銀行の3行が統合したみずほFGにとって、2000年の発足以来の悲願だった。

しかしシステム刷新は何度も挫折し、2002年と2011年には大規模なシステム障害を引き起こした。80年代の非効率的な事務フローが残ったままになるなど、勘定系システムの老朽化は経営の足かせになっていた。

なぜみずほ銀行のシステム刷新は、これほどまでに長引いたのか。そして今回はどうやって完了に導いたのか。

メガバンクの勘定系システムとして初となるSOA(サービス指向アーキテクチャー)全面導入」 「AS IS(現状通り)を禁止した要件定義」「1000社のシステムインテグレーターを巻き込んだプロジェクト管理」など、新勘定系システム「MINORI」開発の全貌と、みずほ銀行がこれから目指す金融デジタル化戦略を、みずほFGにおける19年の苦闘の歴史を追いかけ続けた情報システム専門誌「日経コンピュータ」が解き明かす。

多くの日本企業が直面する情報システムの老朽化問題、「2025年の崖」を乗り越えるヒントがここにある。

書評

まず最初に書いておくが、本書には多くの人が期待しているような内容について、書かれていない

おそらくこの本を手に取った人はみずほ銀行が19年かけたシステム統合において、現場がどれだけ混迷を極めていたかを知りたかったはずだ。定まらない要件、飛び交う怒号、倒れていく開発者、逐次投入される素人、、、こういった内容を期待しているのであれば、本書は期待外れである。

しかしSIerが読むと、「上からの無茶な要求にNOを言えなかったんだろう」「きっと怒号が飛び交っただろう」「この期間担当者は何時間寝られてないんだろう」等、想像できる箇所が多数ある。書かれていない分、逆に想像してしまい心が苦しくなる。

そんなわけでSIerの方は心に余裕のある時に読むことをお勧めする。

一方で、本当に読んでほしいのは経営層の方々である。特に初期のシステム統合計画については「ITに理解のない経営層が経営判断をせずに下に丸投げ」したために中々進まなかった事が書かれている。

簡単に内容を紹介する。

  • 第1部

第1部は新システム「MINORI」の紹介。

4000億円を投じたプロジェクトについて、要件定義の進め方、MINORIの機能などがみずほ銀行幹部へのインタビューと共に掲載されている。

ただ、勝てば官軍、成功した後だからなんとでもいえる、と考えてしまうのは自分の性格が悪いんだろうか。

例えば完全に刷新したはずなのに、勘定系システムはメインフレームCOBOLである。100歩譲ってメインフレームはいいとして、新規開発でCOBOLとはいったいどういう判断だろう。本当に知りたかったのはこのあたりだが、残念ながら本書では触れられていない。

そのほか、日本の金融システムの歴史について簡単にまとめられており、ここは勉強になった。

  • 第2部、第3部

第2部は2度目の障害、第3部は1度目の障害について。

第2部、第3部はおそらく過去の書籍と内容が重複していると思われる。しかし本書の読むべきところはここである。

まず1度目の障害に至るまでの道筋。 経営統合したはいいが、システム統合に関してはITに理解のない経営陣が下に丸投げ。大したシステム統合の方針がないために、各銀行の情報システム担当がそれぞれのSIと組み政治戦。当然のことながら一向に進まないが、システムのリリース日だけは決まっているという状況だった。結果は推して知るべし。

2度目の障害は2011年、東日本大震災での義援金振込が殺到し、システムが処理しきれない数の振込が来たというものだった。1度目の障害以降、旧システムを延命して使用していたのだが、老朽化しそのシステムの様々な制約を知る人がいなくなっていたために招いた事件だった。

障害が起きてからの対応も悪く、システムの長時間停止など思い切った判断をするまでに相当な時間がかかり、障害規模が広がってしまった。

ここでは経営層がどういった判断すべきだったか、どういった仕組みを持っておくべきだったかが掲載されている。

もちろん理想論も多いので、実際にその場になってできるかは別である。しかし、学べるところは多いだろう。