カンテラの光の下で

dNaga392's memorandom

【Hyper-V】VMのディスク領域を増やす

Hyper-VVMのディスク領域を拡張しました。

要点

  1. 「ディスクの編集」で仮想ハードディスクを拡張します。
  2. VMで「ボリュームの拡張」をします。
  3. 回復パーティションがある場合、ツール「AOMEI Partition Assistant」を使います。

内容

VMでライブラリをビルドしていると、ディスク領域不足によるエラー(No space left on device)が発生しました。 確認すると、既定のディスク領域(50GB)を使い切り、空き容量がゼロになっています。

これを解決するため、VMのディスク領域を拡張する方法を調べると、次の記事が見つかりました:

この記事によると、次の2つの手順で実現できるようです:

  1. Hyper-V マネージャーで仮想ハードディスクを拡張
  2. VMで「ボリュームの拡張」

1. Hyper-V マネージャーで仮想ハードディスクを拡張

仮想ハードディスクの拡張では、関連付けられているチェックポイントがあると、 拡張後にはうまく関連付けられないという警告が出ます。

該当のVMは初期に作成したチェックポイントがあったため、 このチェックポイントを適用したのち、全てのチェックポイントを削除して拡張しました。

2. VMで「ボリュームの拡張」

続けて、VMを起動してボリュームの拡張を実行しようとすると、 右クリックメニューから「ボリュームの拡張」が選べませんでした。

これを調べると次の記事に説明がありました:

どうやら拡張するには連続した領域が必要で、今回は「回復パーティション」が未割当て領域との間に挟まっているためできなかったようです。

とはいえ、回復パーティションを削除するのも怖いので、次の記事を参考にしました。

AOMEI Partition Assistant というツールをインストールし、 これを実行することでパーティションの移動および拡張ができました。

余談ですが、とても使いやすかったのでパーティション管理をされる方におすすめです。

【Hyper-V】「一般のアクセスが拒否されました」

概要

Hyper-Vの仮想ハードディスク(Virtual hard disks)を移動して戻したら、「一般のアクセスが拒否されました」と出るようになった。

そもそもなんでそんな事したのかと言うと、チェックポイントがハードディスクを圧迫して削除すらできなっていたためです。 一旦別のストレージに移して、作業領域を空けて、チェックポイントの削除が終わって戻したらこうなった。

この問題は次の記事がとても役に立った。

blog.tpc.jp

対応

原因は、エラーメッセージの通り、実行権限が不足しているためのようだ。

対処法には仮想ハードディスクの再割当てが示されている。 仮想ハードディスクの再割当てをすることで、起動のために必要な権限が割り当てられるらしい。

手順

参考の記事のとおりなのだが、気になったことも含めて自分なりに残す。

  1. Hyper-Vマネージャーの仮想マシン一覧から、(右クリックメニューで)問題を起こしている仮想マシンの設定を開く。
  2. 「ハード ドライブ」設定から現在の仮想ドライブを削除して適用する。
    • 「ハード ドライブ」設定下部の「削除」を押して、「適用」を押す。
      • 注意書きにもある通り、ファイルは削除されないので安心して「削除」して良い。
    • 後ほど再度選択するため、現在の仮想ハードディスク(ファイル)を覚えておく。
  3. ディスクコントローラーにハードドライブを追加しなおす。
    • リストから「ハード ドライブ」を選び、「追加」を押す。
  4. 2 で削除した仮想ハードディスクを再割り当てして適用する。
    • 「参照」を押し、削除した仮想ハードディスクを再度選び、「適用」を押す。

参考資料

バッチファイルを実行ファイルにする

概要

  • DOSのバッチファイル(*.bat)を実行ファイル(*.exe)にする
  • 「Bat To Exe Converter」というツールが便利
  • アイコンも指定できる

背景

普段はPythonを書いているのですが、Windows開発しているとバッチファイルを書くことがあります。

MS-DOSがあれば動くので、Windows環境であれば動作が期待できることがバッチファイルの良い点です。

いつもどおりバッチを作っていると、お客さんから次のような要望をされました。

「それEXEにしてよ」

エンジニアだったらバッチファイルを配布して終了ですが、 バッチファイルに馴染みがない一般ユーザーにはアプリに見えるのが良いとのこと。

そこで、どうやったらできるかなと調べると「Bat To Exe Converter」というものあるらしく、これを使ってみようとなりました。

「Bat To Exe Converter」とは

f:id:dNaga392:20180813012152p:plain

「Bat To Exe Converter」は、テキストエディタのようなGUIに変換設定が表示されているツールです。

左側のペインでバッチファイルを開きつつ、右側のペインでアイコン画像やコンソールを開くかどうかの設定ができます。

イコン画像は *.ico に限るようなので、そこは用意する必要があります。

この設定で実際に作ってみたのが、次のアプリです。

f:id:dNaga392:20180813012747p:plain

○macsですね

更新日時を見て納得してほしいのですが、アプリを実行してテキストを作成することができました。

UIが大変洗練されていて、とても使いやすくおすすめできるツールです。

参考資料

Excelのアドレス文字をPythonで組み立てた

概要

  • xlwings のAPIが遅いので、文字列処理でアドレス文字を求めました

動機

皆さんご存知の通り、Excelにはセルのアドレスを表すA1 とか C3 ってありますよね。

これってVBAだと、RangeオブジェクトのAddressプロパティで取得できて、 xlwingsでもxlwings.Range クラスの get_address メソッドで取得できるんです。

ただ、この処理がちょっと遅い。

一回の処理に0.02~0.04秒程度かかるので、頻繁に呼び出すと急激に処理時間が増えていきます。

そこで、多少のリスクはあってもより短い時間で取得できないかと文字列処理を試みました。

コード

作成したコードは次のとおりです:

列名は、A, B, ..., Z, AA, AB, .... というように記述されるため、26進数でも27進数でもありません(A0などはない)。 そのため、桁上げのとこには少し工夫を入れてあります。

速度的には、上述の処理でほぼゼロ秒まで抑えられました(計測時間では、小数点15桁目まで表示しても0が続くほど)。

感想

コードのコメントにもある通り、xlwings でも得られます。 ではこのコードは同等の処理かというと、サポートしていない機能もあります。

  • 引数チェックがない
    • 不正な値が渡されても処理が進む
  • 最大列数/行数を超えた場合も、アドレス文字列は得られる
    • xlwings だと、上限を超えた場合は例外が送出される

とはいえ、この処理の後にxlwings.Rangeクラスを使うならば、そこでエラーが出るので大きな問題はないかなと思ってます。

スマートではないかなと思いつつも、パフォーマンスが向上できたので個人的には満足です!

参考資料

Pythonのデフォルト引数で注意すること

概要

  • 引数のデフォルト値は 1 度だけしか評価されない
  • つまり、デフォルト引数で指定した値は、関数実行ごとには初期化されない
  • (list や dict のような)変更可能なオブジェクトを指定したい場合は、代わりに None を指定するとよい

現象

関数のデフォルト引数値に、list や dict のように、変更可能(ミュータブル)なオブジェクトを指定したとき、 これは1度しか評価されず、2回目以降はそれを繰り返し使用する。

def f(a, L=[]):
    L.append(a)
    return L

print(f(1))  # => [1]
print(f(2))  # => [1, 2]
print(f(3))  # => [1, 2, 3]

この現象は、 Python ドキュメントに 重要な警告 として記載されている。

これは奇妙な現象にも思えるが、オブジェクトに対して変数を割り当てるという Python の視点から解釈すれば納得することもできるだろう (とはいえ、期待する動作ではないのだが。。。)。

対策

一般的に、このような場合は変更可能(ミュータブル)なオブジェクトの代わりに None を使用する。

def f(a, L=None):
    if L is None:
        L = []
    L.append(a)
    return L

print(f(1))  # => [1]
print(f(2))  # => [2]
print(f(3))  # => [3]

参考資料

【markdown-it】markdownをパースするHTMLを作ってみた

要点

動機

これまで、 markdown ファイルは markdown viewer (Firefox Add-on)を使って表示していたのだが、 他人に見せるときには必ずしもそのアドオンがあるわけでなく、生のmarkdownが表示されることがあった。

そこで、markdownを表示するHTMLを作ってみることにした。

方法

方法は次の手順に分けて対応した。

  1. markdown を読み込む
  2. markdown をパースする

1. markdown を読み込む

markdown の読み込みには、Fetch API を使った。

developer.mozilla.org

Web素人なため、やりたいことがうまく説明できずたどり着くまでに時間がかかったが、 Fetch API により、同じフォルダにある markdown を読むことができた。

fetch('./index.md')
  .then(response => {
    return response.text();
  })
  .then(body => {
     document.body.innerHTML = body;
  });

2. markdown をパースする

markdown のパースには、marked と markdown-it の2つのライブラリが考えられた。

marked を先に知っていたので、まずはこちらでと考えていたが、 markdown-it が拡張性に富んでいるの点と、実際に使っていてオススメだという周囲の助言があったので、markdown-it を採用した。

fetch('./index.md')
  .then(response => {
    return response.text();
  })
  .then(body => {
     var md = window.markdownit();
     document.body.innerHTML = md.render(body);
  });

ライブラリは、環境構築を極力なくすため、 cdnjs から利用することにした。

<script src="https://cdnjs.cloudflare.com/ajax/libs/markdown-it/8.4.1/markdown-it.min.js"></script>

これでもそこそこパースできたが、タイトルがファイル名となってしまいかっこ悪かった。

動機の原点である markdown viewer では、最初のヘッダーがタイトルになっていたので、 これを実現することにした。

実現には、作者 Keith L Robertson 氏のリポジトリを参考とした。

github.com

結果

f:id:dNaga392:20180320011038p:plain

簡単な markdown を HTML に表示することができた。

拙い出来ではあるが、githubに公開した(https://github.com/dNaga392/md-index)。 興味があれば、参考にしたりマサカリ投げていただきたい。

参考

【matplotlib】散布図を3D描画する

要点

使用例

import matplotlib.pyplot as plt
import seaborn as sns
from mpl_toolkits.mplot3d import axes3d  # Axes3D のために必要

df = sns.load_dataset('iris')
xs = df['sepal_length']
ys = df['sepal_width']
zs = df['petal_length']

fig = plt.figure()
ax = fig.add_subplot(1, 1, 1, projection='3d')

ax.scatter(xs, ys, zs)

ax.set_title('Matplot 3d scatter plot')  # タイトル
ax.set_xlabel('sepal_length')  # X軸ラベル
ax.set_ylabel('sepal_width')  # Y軸ラベル
ax.set_zlabel('petal_length')  # Z軸ラベル

plt.show()

mpl-ax3d-scatter.png

特定のグループごとに描画する場合

hue = 'species'
labels = set(df[hue])
dataset = []
for x in labels:
    xs = df[df[hue]==x]['sepal_length']
    ys = df[df[hue]==x]['sepal_width']
    zs = df[df[hue]==x]['petal_length']
    dataset.append((xs, ys, zs))

fig = plt.figure()

ax = fig.add_subplot(1, 1, 1, projection='3d')
for data, label in zip(dataset, labels):
    ax.scatter(xs, ys, zs, label=label)
ax.set_title('Matplot 3d scatter plot')  # タイトル
ax.set_xlabel('sepal_length')  # X軸ラベル
ax.set_ylabel('sepal_width')  # Y軸ラベル
ax.set_zlabel('petal_length')  # Z軸ラベル
ax.legend(loc=2, title='legend', shadow=True)  # 凡例

plt.show()

mpl-ax3d-scatter-hue.png