Python自前のクラスをWithに対応させる

自前のクラス、使い終わったらclose()して欲しい。
将来の自分は、ちゃんとclose()を呼び出してくれるだろうか?
例外が発生した場合も、ちゃんとclose()を呼び出してくれるだろうか?

自前のクラスもwithでクローズ出来たら構文がスッキリする。
Javaならjava.lang.AutoCloseableインターフェースを継承してclose()メソッドを実装すれば、try-with-resource構文が使えるようになりスッキリする。
では、Pythonではどうするのだろうか。

__enter__、__exit__メソッド

自前のクラスに__enter__と__exit__を実装すればよいようだ。

__enter__は__init__の後に呼ばれる。
__enter__は戻り値としてselfを返却すればよい。

__exit__はwithが終わったところで呼び出される。
引き数は必ず4つ受け取る必要がある。withから渡される。
with内で例外が発生したとき、その情報が入っているらしい。

class MyClass:
    def __init__(self, init_value):
        self.xxx = Xxx(init_value)

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.xxx.close()

    def proc(self, proc_value):
        self.xxx.yyy(proc_value)

with MyClass('ABC') as m:
    m.proc('LMN')

このような実装で、withから抜けた時にMyClassがちゃんと閉じられる。

まとめ

FTP接続し複数ファイルを転送したらcloseするとか、
DB接続し処理が完了したらcloseとかいろいろ使えそうだ。
キレイにまとまってよかった。

同じタグの記事
同じカテゴリの記事

Pythonで正規表現

相変わらず、ログの集計。
今回は、ログファイルより特定のキーワードが含まれる行を取得したい。
特定のキーワードは2種類。
ログファイルなので、お決まりのフォーマットで出力されている。
キーワードが2つなので、正規表現を利用してみる。

正規表現モジュール

Pythonで正規表現を利用するためにはreをインポートする。

import re

単純に部分一致する行を見つけたいのであれば以下の様で良い。

text = 'test X start'
if re.search('(X start|X end)', text) is not None:
    print(text)

ファイルの内容を行単位で繰り返し評価する場合は、正規表現オブジェクトをあらかじめ作成しておいた方が良いかも。

r = re.compile('(X start|X end)')
with open('log.log', 'r') as r:
    for line in r:
        if r.search(line) is not None:
            print(line.strip())

re.searchの戻り値を利用する

単純に存在するかどうかを判定するだけであれば、is not Noneで評価すればよいが、matchオブジェクトが返ってきているので、それを使うのも良い。

text = '----+----1----+----2----+----3'
m = re.search('1.*2', text)
print(m.group())
print(m.start())
print(m.end())
print(m.span())
# 1----+----2
# 9
# 20
# (9, 20)

m.start()やm.end()は、文字の切り出しに便利かもしれない。

まとめ

正規表現は書き方がわかるといろいろ便利。

同じタグの記事
同じカテゴリの記事

もうすぐ新元号(続報)

もうすぐ新元号。新元号も決まり、Java Runtimeがアップデートした。
それぞれのJava Runtimeで実行してみる。

サンプルプログラム

import java.util.Date;
import java.util.Locale;
import java.text.DateFormat;
import java.text.SimpleDateFormat;

public class Wareki {
    public static void main(String[] args) {
        System.out.println(System.getProperty("java.version"));
        toWareki("1989/01/07");
        toWareki("1989/01/08");
        toWareki("2019/04/30");
        toWareki("2019/05/01");
    }

    public static void toWareki(String seireki) {
        try {
            DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, Locale.JAPAN);
            Date date = df.parse(seireki);
            SimpleDateFormat sdf = new SimpleDateFormat("GGGGyyyy.M.d", new Locale("ja", "JP", "JP"));
            System.out.println(seireki + ":" + sdf.format(date));
        } catch (Exception e) {
            System.out.println("Err." + e.getMessage());
        }
    }
}

平成の変わり目をjava.versionと供に出力する。

実行

Java 6

1.6.0_45
1989/01/07:昭和64.1.7
1989/01/08:平成元.1.8
2019/04/30:平成31.4.30
2019/05/01:平成31.5.1

Java 7

1.7.0_79
1989/01/07:昭和64.1.7
1989/01/08:平成元.1.8
2019/04/30:平成31.4.30
2019/05/01:平成31.5.1

1.7.0_80
1989/01/07:昭和64.1.7
1989/01/08:平成元.1.8
2019/04/30:平成31.4.30
2019/05/01:平成31.5.1

Java 8

1.8.0_191
1989/01/07:昭和64.1.7
1989/01/08:平成元.1.8
2019/04/30:平成31.4.30
2019/05/01:平成31.5.1

1.8.0_201
1989/01/07:昭和64.1.7
1989/01/08:平成元.1.8
2019/04/30:平成31.4.30
2019/05/01:平成31.5.1

1.8.0_211
1989/01/07:昭和64.1.7
1989/01/08:平成元.1.8
2019/04/30:平成31.4.30
2019/05/01:令和元.5.1

Java 11

11
1989/01/07:昭和64.1.7
1989/01/08:平成元.1.8
2019/04/30:平成31.4.30
2019/05/01:元号元.5.1

11.0.1
1989/01/07:昭和64.1.7
1989/01/08:平成元.1.8
2019/04/30:平成31.4.30
2019/05/01:元号元.5.1

11.0.2
1989/01/07:昭和64.1.7
1989/01/08:平成元.1.8
2019/04/30:平成31.4.30
2019/05/01:元号元.5.1

11.0.3
1989/01/07:昭和64.1.7
1989/01/08:平成元.1.8
2019/04/30:平成31.4.30
2019/05/01:令和元.5.1

Java 12

12
1989/01/07:昭和64.1.7
1989/01/08:平成元.1.8
2019/04/30:平成31.4.30
2019/05/01:元号元.5.1

12.0.1
1989/01/07:昭和64.1.7
1989/01/08:平成元.1.8
2019/04/30:平成31.4.30
2019/05/01:令和元.5.1

1.6、1.7は令和に対応していない。
1.8は1.8.0_211から対応している。
11は11.0.3から対応している。11は最初から新元号になることはわかっていたようで元号元と出力されている。
12は12.0.1から対応している。12も最初から元号元の表記がある。

まとめ

DotNetでは和暦の対応が急遽変更になったそうですが、Javaはそのまま元号が令和になっただけで大きな変更はなさそう。
しかし、DotNetの対応で確かにそうだなあと思ったのは、まだ元号が変わったわけではないので、現在の出力は平成31.5.1でも良いような気がする。令和になるのは令和元.5.1以降でも。
ましてや元号元.5.1なんて出力されたら、もっと困ってしまう。Java11で和暦変換していた人はどうしていたのだろうか?

同じタグの記事
同じカテゴリの記事

Pythonで昨日

FTPで昨日のログファイルを取得したい。
FTP取得自体は、以前から行っていたが昨日を求める必要がある。

Pythonで昨日を取得する

datetime.timedeltaで一日を表現して、それをマイナスすればよいようだ

import datetime
now = datetime.datetime.now()

# 今
print(now)
# 一日前
print(now - datetime.timedelta(days=1))

すばらしい。1日はdays=1で表現できて、それを減算すると一日前のようだ。

ならば、7日前は1週間前だ。

print(now - datetime.timedelta(days=7))

7日前は1週間前という表現もできるようだ。

print(now - datetime.timedelta(weeks=1))

1時間前も取得できる。

print(now - datetime.timedelta(hours=1))

プラスすれば1時間後

print(now + datetime.timedelta(hours=1))

datetimeの引き算の結果もtimedelta

そういえば、datetimeとdatetimeの引き算の結果もtimedeltaだった。

before = datetime.datetime.strptime('2019/4/16 16:30', '%Y/%m/%d %H:%M')
after = datetime.datetime.strptime('2019/4/17 17:15', '%Y/%m/%d %H:%M')
delta = after - before
print(delta.days)
print(delta.seconds)

daysは経過日数、secoundsは経過秒数が得られる。

まとめ

Pythonの日付時刻は一貫性があって美しい。

同じタグの記事
同じカテゴリの記事

Rubyでメソッドを定義する

Rubyの事を忘れないように、週に1回はRubyでツールを作る事にしている。
毎週作っている割に、やっと巡ってきたメソッドの定義の仕方。

Rubyでメソッドの定義

特に難しいことはなかった。

def my_func(arg1, arg2="Ruby")
    puts "#{arg1}, #{arg2} !"
    return arg1
end

my_func "Hello"
my_func "Hello", "JRuby"

my_funcが作成され、arg2はオプションになる。
戻り値はreturnで返す。returnは省略可能(Perlみたい)。

名前付き引数

def my_func(greet:, lang: "Ruby")
  puts "#{greet}, #{lang}!"
  return greet
end

my_func greet: "Hello"
my_func greet: "Hello", lang: "JRuby"

名前付き引数も使える。しかし、Pythonとは異なり、名前付き引数は必ず名前を指定しなくてはいけない。順番と名前をそれぞれ考慮してくれる訳では無いようだ。

まとめ

関数呼び出しにカッコをつけなくて良いのは、慣れると便利な気がしてきた。
今までは、カッコが当たり前だったのに、なくて良いとわかると付ける気がしない。Perlを思い出してきた。

同じタグの記事
同じカテゴリの記事

WordPressのGutenbergでブロックの追加ができないとき

WordPressも5.1がリリースされたので、そろそろ4系からバージョンアップすることにした。
新しいエディタになったら、今までのMarkdownプラグインが使えなくなってしまうのかと思いバージョンアップを避けていたが、試しにWordPress5.1の環境を用意しMarkdownをコピー&ペーストしたところ、プラグインなしでもMarkdownに対応し、それもブロックまで勝手に作ってくれていた。これは便利だ。

バージョンアップしたWordPress5.1

事前検証では全く問題なかったWordPress5.1だが、バージョンアップしたWordPress5.1では、Markdownをコピー&ペーストすると、そのままMarkdownが張り付いてしまう。それどころか手動でブロックを作ろうとしても、ブロックが作成できない。

ブロックが作成できなかった原因

「ユーザ」-「プロフィール」-「WordPressビジュアルリッチエディターを利用しない」のチェックが入っていると、ブロックの作成ができないようだ。
このチェックを外したところ、ブロックの作成ができるようになったし、Markdownの貼り付けも問題なく行われるようになった。

その他の問題点

プログラムの記事を書いた時、ソースコードを貼り付けているが、従来使っていたプラグインCodeColorerが新しいGutenbergには対応していなかった。これからはSyntaxHiglighter Evolvedというプラグインを使えば良いようだ。これにより、ソースコードのブロックに言語指定ができるようになり、そのハイライトが適用される。
ちなみに、過去の記事はCodeColorerで色付けを行なっているため、CodeColorerプラグインを削除してはいけない。

その他の問題点2

ブロック内でエンターキーを叩くと、新しいブロックが作成されてしまう。長文を書く場合はこれで良いかもしれないけど、メールを書くように改行を繰り返したいときは、この仕様は不便だった。しかし、この仕様が放置されているはずもなく「Shift+Enter」をクリックすることによりブロック内で改行ができた。

まとめ

慣れてしまえば、WordPress5.1で全く問題ない。むしろ見た目に美しいし、文書管理も便利になっている。本当なら、過去の記事もコンバート出来たら完璧なんだろうけど。

同じタグの記事
  • ありません。
同じカテゴリの記事

もうすぐ新元号

もうすぐ新しい元号になる。Windowsは新元号になったら、Windowsアップデートで新元号に対応するらしい。
いつも使っているJavaはどうなのだろう。そもそもJavaで元号変換できるのだろうか。

SimpleDateFormat

Javaの日付フォーマットでおなじみSimpleDateFormatで元号表示できた。

import java.util.Date;
import java.util.Locale;
import java.util.Calendar;
import java.text.DateFormat;
import java.text.SimpleDateFormat;

var df = DateFormat.getDateInstance(DateFormat.SHORT, Locale.JAPAN);
var dateArray = new Date[] {
    df.parse("1989/01/06"),
    df.parse("1989/01/07"),
    df.parse("1989/01/08"),
    df.parse("1989/01/09"),
    df.parse("2019/04/29"),
    df.parse("2019/04/30"),
    df.parse("2019/05/01"),
    df.parse("2019/05/02"),
};

var dateFormatArray = new SimpleDateFormat[] {
    new SimpleDateFormat("GGGGy.M.d", new Locale("ja", "JP", "JP")),
    new SimpleDateFormat("GGGGyy.M.d", new Locale("ja", "JP", "JP")),
    new SimpleDateFormat("GGGGyyy.M.d", new Locale("ja", "JP", "JP")),
    new SimpleDateFormat("GGGGyyyy.M.d", new Locale("ja", "JP", "JP")),
};

for (var format : dateFormatArray) {
    for (var date : dateArray) {
        System.out.println(format.format(date));
    }
    System.out.println("--");
}
昭和64.1.6
昭和64.1.7
平成1.1.8
平成1.1.9
平成31.4.29
平成31.4.30
元号1.5.1
元号1.5.2
--
昭和64.1.6
昭和64.1.7
平成01.1.8
平成01.1.9
平成31.4.29
平成31.4.30
元号01.5.1
元号01.5.2
--
昭和064.1.6
昭和064.1.7
平成001.1.8
平成001.1.9
平成031.4.29
平成031.4.30
元号001.5.1
元号001.5.2
--
昭和64.1.6
昭和64.1.7
平成元.1.8
平成元.1.9
平成31.4.29
平成31.4.30
元号元.5.1
元号元.5.2
--

元号が表示できた。それもGGGGyyyyにすると、元年が出力される。
すばらしい。
java12で実行したが、未来の元号は「元号」と表示されるようだ。今しか見られないのだろうか。

まとめ

でも、社内システムで和暦を使うことは少ないと思う。
jshellを使って動かしてみたが、動作確認には便利だった。
java10以降使えるvarも意外と便利だし正しく動いた。

jdk1.8.0_201でコンパイルできるように修正して実行したところ、2019.5.1は平成31.5.1が返ってきた。

同じタグの記事
同じカテゴリの記事

clipコマンド

ネットを徘徊していたら、Windowsバッチでclipというコマンドが使える事を知った。
このコマンドを使うことで、コマンドプロンプトからクリップボードへ出力したり、クリップボードから他のコマンドへ出力することができるようだ。
Windowsで標準入力を備えているコマンドはあまり知らないが、標準出力をクリップボードに飛ばせるのは便利だ。

clipコマンド

clip /?とすることで、clipコマンドのヘルプを確認できる。

C:\Users\User>CLIP /?

CLIP

説明:
    コマンド ライン ツールの出力を Windows クリップボードにリダイレクトします。
    その出力されたテキストをほかのプログラムに貼り付けることができます。

パラメーター一覧:
    /?                  このヘルプを表示します。

例:
    DIR | CLIP          現在のディレクトリ一覧のコピーを Windows クリップボード
                        に貼り付けます。

    CLIP < README.TXT   readme.txt ファイルのテキストのコピーを Windows
                        クリップボードに貼り付けます。

C:\Users\User>

このヘルプはコマンドプロンプトからコピーしてからペーストしている。
このコピー操作もclipコマンドで実行できる。

C:\Users\User>CLIP /? | CLIP

C:\Users\User>

標準出力はCLIPコマンドに吸い込まれたので何も出力されなくなる。
しかし、ここでペーストしてみると

CLIP

説明:
    コマンド ライン ツールの出力を Windows クリップボードにリダイレクトします。
    その出力されたテキストをほかのプログラムに貼り付けることができます。

パラメーター一覧:
    /?                  このヘルプを表示します。

例:
    DIR | CLIP          現在のディレクトリ一覧のコピーを Windows クリップボード
                        に貼り付けます。

    CLIP < README.TXT   readme.txt ファイルのテキストのコピーを Windows
                        クリップボードに貼り付けます。

クリップボードの保存されている。素晴らしい。

まとめ

DIRやTREEなどコピペすることが多々あるので、このコマンドさえあればコピーの手間がなくなる。良いコマンドを知った。
忘れないように、ちょくちょく使うようにしよう。

同じタグの記事
同じカテゴリの記事

JRubyやり直し

JRubyを使わなくなっていた。理由はjarファイルの指定をアスタリスクで複数指定できなかったから(Windowsの時)。ちょっとAPI呼びたい時に面倒だったから。
しかし、Jythonではどうしても文字列の対応が難しい部分があり、JRubyを使おうと思った。
JRubyの構文が全く思いだせない。

ディレクトリ内のファイル(ディレクトリ)を表示する

Dir.open(".").each do |f|
  puts f
end

完結だ。覚えればPython並みに便利なツールになるんだろう。

ファイルかどうかを判断する

dir = "."
Dir.open(dir).each do |f|
  path = File.join(dir, f)
  puts path
  puts File.file?(path)
end

パスの結合にはFile.join()を使う。

リストの定義、追加、ソート、イテレート

よく使う方法を考えて、リストの中には敢えてHashを入れる

my_list = []
my_list << {:id => "1", :name => "John"}
my_list << {:id => "2", :name => "Bob"}
my_list << {:id => "3", :name => "Ken"}
my_list.sort! do |a,b|
  a[:name] <=> b[:name]
end
my_list.each do |i|
  puts i[:name]
  puts i[:id]
end

Hashの任意の項目でソートできる。
ソーターの指定が簡単にブロックを指定できるところが嬉しい。

文字列の便利な用法

name = "Ruby"
puts "Hello, #{name}!"
puts name.downcase
puts name.upcase

この辺りも簡単。最初はすっかり忘れていてsprintf使っていたけど、分が短い時は#{xxx}の方がずっと完結。

ifブロック

a = 10
if a == 3 then
  #
elsif a == 5 then
  #
else
  #
end

endをついつい忘れてしまう。Pythonの癖だ。

関数の作成

def my_func(x, y=",")
  puts x + y + x + y + x
end
my_func "aaa"
my_func "bbb", ""
my_func("ccc", "-")

デフォルト引数が使える。ほとんどの言語で使えるけどJavaでは使えない。なぜJavaはデフォルト引数を使わせてくれないのだろう。引数違いのメソッドをたくさん作るの面倒なのだが。

まとめ

Rubyなかなか面白い。
タブのスペースの数が2つなので、ifをいっぱい入れ子にするとend end endが沢山ならんで面白い(極端な入れ子の実装の話は置いておいて)。
忘れないうちに、もう一つJRubyでプログラムを作りたい。

同じタグの記事
同じカテゴリの記事

Majestouch 2 Convertible 茶軸

会社で3カ月ほどMajestouch 2 Convertibleの赤軸静音モデルを使っている。ダイアテックオンラインの限定商品で、会社で使うには静音でないと近所迷惑になると思い、静音赤軸にした。
しかし、この滑らかキーボードでもキータッチが重く感じるようになってきた。スイッチに赤軸静音を選んだためか

静音化

HHKBのType-Sと同じで、かみ合わせをタイトにしたりしているのだろう。
以前、HHKBの45gが重く感じると書いたことがあるが、これはType-Sのせいだった。BTは軽かった。Type-Sは噛み合わせがタイトになっているぶん、よほどまっすく押し込まないと抵抗が生まれるのだろう。これが、Cherry 赤軸静音にも言えるのだと思う。

Majestouch 2 Convertible 茶軸

楽天スーパーセールの勢いもあって買ってしまった。
見た目は赤軸静音も茶軸も全く同じ。新品なので艶消しが美しいくらいか。

早速、キータッチは・・・
軽い。軽く感じる。タカタカ鳴る音に騙されているかもしれないが軽く感じる。これで、タイピングが早くなっているかというと、全くそんなことはないが気持ちがいい。
やはり、これがメカニカルスイッチの気持ちよさなんだろう。機能性で言えば、赤軸静音なのかもしれないが、気分を盛り上げるためには茶軸は良い。

まとめ

またキーボードを購入してしまった。毎日異なるキーボードを使っても、すべてを使うのには1週間かかる。それでもMajestouch 2 Convertible 茶軸は大事にしておきたいと思う。

同じタグの記事
同じカテゴリの記事