2024年7月15日月曜日

Dynabook UX/23にDebian 12をインストール

Dell mini9のために32bit(i386)用のDebian12のインストールUSBを作ったのでdynabook UX/23にもインストールしてみた。こちらは古いものですが、キーボードが打ちやすいネットブックです。CPUは、Atom N280なで、32bitのものをいれることになります。メモリは2GBに増設してあってWindows XPで動いていました。

Windows XPのHDDはそのまま残しておいて、Netacの内臓SSD256GB(2.5インチ、SATA、厚さ7mm)のものを購入して交換しました。 バッテリーをはずした後に、本体の裏ブタをトルクスドライバー(T6)で開けて、HDDをスライドさせると簡単に外れました。蓋のほうにスペーサーがついていて、取り付け時は、HDDが外れないようにスライドさせるスペースが埋まるようになっていました。取り外したHDDについている金具を取り外して、新しいSSDに取り付けて、同じように本体に収めました。この金具を取り付けている4本のネジが緩まないように強く締まっていましたので、外すのにネジ山をつぶさないように注意が必要でした。

ふたを閉めてもとにもどしたら、バッテリーをもどして、電源ケーブルをつなぎます。Debian12のインストール用のUSBを本体に差してから、電源ボタンを入れて、F2キーを押しておくと、BIOS画面になりました。電源を入れる前にUSBキーを刺してあるので、それが認識されています。起動先としてUSBを優先に設定して、起動させます。

UX/23は、Dell mini9と違って、wifiをすぐに認識しました。インストール用のネットワーク経路に、どちらかの接続が選べるようです。デスクトップ環境をDell mini9と同じようにLXDEでインストールしました。なにも問題なくインストールは終了し、Debian12が起動しました。

wifiは、connmanというネットワークのマネージャーで設定するようです。 ネットワークの設定は、いろいろあって分かりにくいですね。 Network Manager(nmcli)を使ってもよいとありますが、いろいろ試すのも面倒です。 とりあえず、connman setupを選ぶと、正常にwifiのリストが表示され、問題なく接続はされました。よくわからないのは、ここからで別の場所でwifiを使おうとすると、アクセスポイントには接続されますが、いろいろなWebページは開かないという状況になりました。インストールした場所のwifiでは、正常につながっているようです。どうやら、DHCP経由で、DNSがうまく設定されないようすです。ConnmanによるDNSのマネージメントについていろいろ報告があるみたいですが、とりあえず/etc/resolv.confにGoogle Public DNS(8.8.8.8と8.8.4.4)を追記して、つなげることができました。

2024年6月23日日曜日

lubuntu 24.04 LTSでwxPython4.2.1

古いPCにLinuxを入れて使えるようにしています。 Lubuntu 24.04 LTSを古いデスクトップPCに入れて使っています。 リモートデスクトップとpythonくらいしか利用しませんので 古いパソコンでも十分な用途です。 pythonは、python3が利用でます。 さて、GUIにwxPythonをよく利用していたのですが、 そのようなスクリプトを動かすときにwxPythonをインストールする必要があります。 Windowsでは、pipを用いてインストールしていますが、 lubuntuでは、aptを使ってインストールするようです。
apt install python3-wxtools
でインストールできました。

さて、これで使えるなら問題よいのですが、しばしば 仮想環境を利用することが増えています。python3では、 すぐにvenvが利用できるようになっています。 たとえば、

mkdir myproject
cd myproject
python3 -m venv myenv
として、myprojectフォルダの中に、 そのプロジェクト用のmyenvという仮想環境を作って利用したりします。 その仮想環境を利用するには、
cd myproject
source myenv/bin/activate
として、仮想環境のフォルダ内にあるactivateスクリプトを用いて利用できるようにします。 アクティベートするといいます。 ここで pip install numpy とすると仮想環境にnumpyがインストールされるわけです。 ある環境がアクティベートされた状態で起動されるpythonでは、 その環境にインストールされたモジュールが利用できるというわけです。 環境を戻すには、deactivateを実行します。

さて、この仮想環境へはpipを用いてモジュールをインストールします。 pip install wxPythonとしてwxPythonををpipでインストールしようとすると、 ビルドエラーが出て停止してしまいました。 こちら https://wxpython.org/blog/2017-08-17-builds-for-linux-with-pip/index.html のサイトを参考にしてインストールをしました。

"What You Need"の箇所にビルドに必要なライブラリが記載されています。 地道にひとつづつインストールしていきます。 私の環境では、

sudo apt install python-dev
sudo apt install libgtk-3-dev
sudo apt install libgstreamer1.0-dev
sudo apt install libgstreamer-plugins-base1.0-dev
sudo apt install libglu1-mesa-dev mesa-common-dev freeglut3-dev
sudo apt list |grep libwebkit2gtk
sudo apt install libwebkit2gtk-4.1-dev
sudo apt install libjpeg-dev
sudo apt install libpng-dev
sudo apt install libtiff-dev
sudo apt install libsdl-dev
sudo apt install libnotify-dev
sudo apt install libsm-dev
としていきました。すでにインストールされているものもいくつかありましたが、
順番に検索エンジンを利用しながら確認していきました。
途中どれをインストールするかlistを見て確認したりもしています。

あとは、"Build Steps"にあることを順番にしていくだけです。もちろん、 ファイル名はダウンロードされたものに合わせて修正します。 書いてある通りにすると無事にwheelファイルがビルドされ、 wxPythonを利用することができるようになりました。

このようにしてpython3.12でwxPython4.2.1が動きました。 ただし、現在ダウンロードされたファイルをコンパイルしたものは、 pythonを起動してimport wxのあとすぐにquit()してもセグメンテーションフォールトを起こします。 "wxpython 4.2.1 segmentation fault"で検索してみるとすでに報告はあるようです。 とりあえずは利用できるので、修正を待ちます。 ちなみに、仮想環境ではなくaptでインストールした環境ではそのようなエラーは起こっていません。

DELL Inspiron Mini9 にDebian 12 bookwormをインストールしてみた

使っていないDell Inspiron Mini9がありました。 もともとWindows XPで使っていたものです。 XPのサポート切れからしばらくたち、 当時のWebブラウザを使っても開けないページも増えてきました。 そのうちLinuxでも入れてみようと置いてあったが、 32bitアーキテクチャがサポート対象から外されて行っている傾向があるので、 Debian12(bookworm)を試してみました。

作業した部屋のネットワーク環境がwifiだけの場所だったので、 ネットワークがすぐに使えるとは考えられないため、 debian-12.5.0-i386-DVD-1.iso をダウンロードしました。 ファイルSHA256SUMS.txtもダウンロードします。 インストール用のUSBは、手元にあった16GBのものを利用しました。 isoのサイズは、およそ3.7GBですので、こんな大きなものは必要なかったでしょう。 USBの作成環境は目の前にあるWindows11のノートパソコンです。

まず、ダウンロードしたisoイメージのハッシュ値を計算して確認します。 コマンドプロンプトを開いて、ダウンロードフォルダへ移動し以下のコマンドでSHA256のハッシュ値を調べます。

certutil -hashfile debian-12.5.0-i386-DVD-1.iso SHA256
出力された文字列とSHA256SUMS.txtの中にあるDVD-1.isoのハッシュ値を比較し 同じものであることを確認します。 正しくダウンロードされていたら、このisoイメージをUSBに書き込み インストール用のUSBを作成します。

USBへのisoイメージの書き込みには、Rufus 4.5(rufus-4.5p.exeポータブル版)を利用しました。 Deviceで、書き込む先のUSBを選んで、ブートの種類の箇所の選択ボタンを押してISOイメージを選択します。 パーティション構成はMBR、ターゲットシステムはBIOSまたはUEFIが選ばれた状態になっています。 書き込むUSBによるのでしょうが、 フォーマットオプションのファイルシステムは、FAT32(規定)クラスターサイズは8192バイト(規定)となっています。 すべてデフォルト状態のままスタートして書き込みを開始しました。 3.7GBのイメージの書き込みなので、時間はかかりましたが、インストール用USBが作成されました。

Mini9にインストール用USBを刺して、起動します。 キー2を押してBIOS設定を開いてUSB優先で起動できるように設定し、再び起動させます。 あとは、グラフィカルインストーラーで指示に従ってインストールしていきます。 私のMini9はUS配列キーボードなのでキーボードの選択で米国を選びました。 途中wifiのところでb43-ucode15.fwといファームウェアが必要だよと言われますが、 ここでは無視して続けていきます。 Mini9は、Etherの口がありますので、あとでネットワークケーブルを使って接続して設定するつもりでいます。 DHCPで接続が試みられますが、現時点でケーブルの接続もしていないので、接続されないまま続けます。 パーティションは推奨設定(初心者用設定)で進めて、 ソフトウェアの選択でデスクトップ環境にGNOMEではなくLXDEを択しました。 トラブルなくインストールが終了し、起動ディスクを抜いて再起動かけると無事に起動させることができました。

ネットワークケーブルが利用できる場所に移動して、ケーブルを接続するとDHCPで問題なく接続されました。 DVDでインストールしたので、リポジトリの設定ができていないので、 /etc/apt/sources.list ファイルを編集しました。 suコマンドでスーパーユーザーになって編集します。 Googleで、"debian bookworm repository"を検索して設定を参考にさせていただきました。

ファイルを編集したのちapt updateし、apt upgradeしてみますと問題はなさそうです。 firefoxがインストールされているので、youtubuに接続してみると動画はカクカクですが音もちゃんと出ています。 add userで、sudoグループにユーザー名を追加し、sudoできるようににしました。

日本語入力は、fcitx-mozcを利用します。 apt install fcitx-mozcをし、 apt remove uim-mozcをしました。

タッチパッドは、タップでクリックができなかったので、 パス/etc/X11/xorg.conf.d/に30-touchpad.confというファイルを作成しました。 内容は、以下のとおりです。

Section "InputClass"
Identifier "touchpad"
Driver "libinput"
MatchIsTouchpad "on"
Option "Tapping" "on"
EndSection

wifiでの接続ですが、 https://wiki.debian.org/bcm43xx を参考にして、

deb http://deb.debian.org/debian/ bookworm main contrib non-free
を/etc/apt/source.listに追加し、 sudo apt updateを行った後、
sudo apt install firmware-b43-installer
をします。メニューの設定から高度なネットワーク設定でwifiのアクセスポイントを追加したら 利用できるようになりました。 LibreOffice 7.4が入っているので動かしてみても、問題はなさそうです。 pythonも3.11が利用できています。 SMPlayerでSMTubeを使って、YouTubeを観てみたら滑らかに再生できました。 古くて小さいノートパソコンですが、用途によっては現役として十分利用できそうです。

2020年10月19日月曜日

wxPython 4.1のwx.ListCtrlでCheckBox

wxPythonで行の頭にCheckBoxのついたリストコントールを使いたいとき、 wx.ListCtrlにCheckListCtrlMixinを使っていた。 wxPythonの4.1で、以前のスクリプトを動かしたところこれが動かなかった。

どうやら、CheckListCtrlMixinで定義されていたCheckItem()メソッドが、 wx.ListCtrlのbuilt-ins functionになったために、 そちらが呼び出されて動作しない様子である。 新しい、wx.ListCtrlには、CheckListCtrlMixinを利用しなくても、 CheckBox付きのwx.ListCtrlが利用できるようになったらしい。

wxPythonのページに、EnableCheckBoxes(enable=True)のメソッドが説明されていた。 これを使えばよいが、これまで使いたいスクリプトをとりあえす 動かしたいということであれば、 CheckItem()をMixinのものに上書きすると動作するようになった。

def MyCheckItem(self, index, check=True):
    img_idx = self.GetItem(index).GetImage()
    if img_idx == 0 and check:
        self.SetItemImage(index, 1)
        self.OnCheckItem(index, True)
    elif img_idx == 1 and not check:
        self.SetItemImage(index, 0)
        self.OnCheckItem(index, False)

wx.ListCtrl.CheckItem = MyCheckItem
しかしながら、そのうち直さなくてはならないということで、 EnableCheckBoxes()を使ったものを書いてみた。
import wx
import wx.lib.mixins.listctrl

class CheckListCtrl(wx.ListCtrl):
    def __init__(self, panel, style):
        wx.ListCtrl.__init__(self, panel, -1, 
                style=wx.LC_REPORT,size=wx.Size(400, 300))
        self.EnableCheckBoxes(enable=True)
        self.Bind(wx.EVT_LIST_ITEM_CHECKED, self._OnCheckItem)
        self.Bind(wx.EVT_LIST_ITEM_UNCHECKED, self._OnUnCheckItem)

    def _OnCheckItem(self, evt):
        self.OnCheckItem(evt.Index, True)

    def _OnUnCheckItem(self, evt):
        self.OnCheckItem(evt.Index, False)
        
    def OnCheckItem(self, index, flag):
        print(index, flag)

class AppFrame(wx.Frame):
    def __init__(self, *args, **kwargs):

        wx.Frame.__init__(self, None ,wx.ID_ANY, 'CheckListCtrl', size=(400,300))

        self.list = CheckListCtrl(self, style=wx.LC_REPORT)

        titles = ("check", "title1", "title2")

        for index, title in enumerate(titles):
            self.list.InsertColumn(index, title, wx.LIST_FORMAT_LEFT)

        for index, title in enumerate(titles):
            self.list.Append(["name%d" % index, "value", "value" ]) 

        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.sizer.Add(self.list, 1, wx.EXPAND, border=0)
        self.SetSizer(self.sizer)
        self.Show()

if __name__ == "__main__":
    app = wx.App()
    win = AppFrame()
    app.MainLoop()
wx.EVT_LIST_ITEM_CHECKEDとwx.EVT_LIST_ITEM_UNCHECKEDをハンドルして、 従来のMixInを利用した場合と同じ引数で、 OnCheckItem()メソッドを呼び出すようにしてみた。

2020年8月22日土曜日

NimでZipファイルにしたテキストを読む

nimというプログラミング言語を試してみた。 pythonのように書けるけど、静的な型付けのコンパイラなので、 実行速度のパフォーマンスがよいということである。

大きなカンマ区切りの値(CSV)やタブ区切りの値(TSV)といった テキストデータをzipで圧縮するとだいぶ小さくなるので、 そのようにして保存しておくことも多い。 そのようなテキストファイルを読み込みたいときに、 zipファイルを扱うモジュールが利用できると便利である。

そこで、datafile.txtというテキストファイルをzip圧縮した、 datafile.zipを読み込んで、各行をプリントするだけというスクリプトを書いてみた。

Python(v3.83 windows 64bit)では、以下のようなスクリプトになる。

import io
import zipfile

def readzip():
    filename = "datafile.zip"
    try:
        z = zipfile.ZipFile(filename, 'r')
    except:
        print("Opening zip failed")
        exit(-1)
    try:
        for fname in z.namelist():
            print(fname)
            fp = io.TextIOWrapper(z.open(fname, 'r'))
            line = fp.readline().strip()
            while line:
                print(line)
                line = fp.readline().strip()
            fp.close()
    finally:
        z.close()

if __name__ == '__main__':
    readzip()       
nimでは、zipパッケージにあるzipfilesモジュールを利用する。
import streams
import zip\zipfiles

proc readzip() =
    var filename = "datafile.zip"
    var z: ZipArchive
    var line = ""
    if not z.open(filename):
        echo "Opening zip failed"
        quit(1)
    try:
        for f in walkFiles(z):
            echo f
            var fs = z.getStream(f)
            while fs.readLine(line):
                echo line
            fs.close()
    finally:
        z.close()

when isMainModule:
    readzip()
コンパイルは、readzip.nimというファイルに書いたとすると、
nim c readzip.nim
でできるが、その前にzipパッケージをインストールする必要がある。 Gitがインストールされていれば、
nimble install zip
でインストールできる。 さらに、Windowsでコンパイルすると、gccでコンパイルされるときに エラーで止まってしまった。 こちらにあるように、修正するとコンパイルできた。

ついでなので、Julia(v1.5 windows 64-bit)でも書いてみた。 juliaでは、ZipFile.jlが利用できる。

using Pkg
Pkg.add("ZipFile")
としてインストールできた。
using ZipFile

function readzip()
    filename = "datafile.zip"
    local z

    try
        z = ZipFile.Reader(filename)
    catch
        println("Opening zip failed")
        exit(-1)
    end

    try
        for f in z.files
            println(f.name)

            while !eof(f)
                line = readline(f)
                println(line)
            end
        end
    finally
        close(z)
    end
end

readzip()       
Juliaでは、tryブロックもスコープを作るようで、tryブロック内で作った変数zを、 そのtryブロックから出た後でも利用するために、local z宣言をしている。

どれも似たような感じに書けたが、Juliaは、関数が充実しているからかシンプルに感じる。 whileのループは、eachline(f)を用いたforループで書くと、すっきりする。

2020年8月10日月曜日

タイムスタンプを得る(Rust)

Rustをインストールしたので、練習してみる。 プログラムの出力結果に、実行日時を付加するときにタイムスタンプがほしいことがある。 ここでのタイムスタンプは、"2020/08/10 09:00:35"といった形に現在日時を示す文字列である。 それを得る関数timestamp_now()を書いてみようと思った。

Pythonでは、

import datetime
dt = datetime.datetime.now()
timestamp_now = "%04d/%02d/%02d %02d:%02d:%02d" % (
    dt.year, dt.month, dt.day, 
    dt.hour, dt.minute, dt.second)
と簡単に得られる。

Rustでは、chronoという外部クレートを用いることで簡単に得られるようである。 ここでは、chronoを使わずに、std::timeを用いてタイムスタンプを得る。 std::time::SystemTime::now()を用いて、現在時刻のUNIX_EPOCHタイムからの秒数を得て、 Fairfieldの公式を使って日数を勘定すればタイムスタンプが得られるだろうということである。

現在時刻とUNIX_EPOCHタイムとの差を得る関数は以下の通りでよいだろう。

fn now_from_unix_epoch() -> f64 {
    let now = std::time::SystemTime::now();
    now.duration_since(std::time::SystemTime::UNIX_EPOCH).unwrap().as_secs_f64()
}
次に、その秒数が何日に相当するかを評価する関数である。 Rustは、Pythonのように、気軽に複数の値を返せるようであるので、 のこりの秒数から時、分、秒を返すことにしてある。 tzは、タイムゾーンによる時間のズレを補正するために入れてある。 日本時間はUTCより9時間進んでいるので、9を入れて計算すると日本時間となる。
fn counts_day_from_sec(seconds:f64, tz:f64) -> (u32, u32, u32, f64) {
    const DAY_SEC:f64 = 60.0*60.0*24.0;
    const HOUR_SEC:f64 = 60.0*60.0;
    const MIN_SEC: f64 = 60.0;
    let days = ((seconds + tz * HOUR_SEC)/DAY_SEC).floor();
    let remain_sec = (seconds + tz * HOUR_SEC) - (days*DAY_SEC) as f64;
    let hour = (remain_sec/HOUR_SEC).floor();
    let remain_sec = remain_sec - (hour*HOUR_SEC) as f64;
    let min = (remain_sec/MIN_SEC).floor();
    let sec = remain_sec - (min*MIN_SEC) as f64;
    (days as u32, hour as u32, min as u32, sec) 
}    
得られた日数から日付を得るために、日付から日数を得るFairfiledの公式を使った関数を作る。 1月、2月の時は、年を1年戻して、それぞれ13月、14月として計算する必要がある。
fn daycounts_fairfield(year:u32, month:u32, day:u32) -> u32 {
    let mut y = year;
    let mut m = month;
    if month < 3 {
        y = year -1;
        m = month +12;
    }
    let day_before_the_year = 365 * (y-1);
    let day_of_leep_year = y/4-y/100+y/400;
    let day_in_the_year = 31 +28 +306*(m+1)/10-122 +day;
    (day_before_the_year + day_of_leep_year + day_in_the_year) as u32
}    
次に、この関数を用いて日付を探せばよい。年、月、日を返す。
fn days_to_date(days:u32) -> (u32, u32, u32) {
    let unix_epoch = daycounts_fairfield(1970, 1, 1);
    let mut year = 1970;
    while daycounts_fairfield(year, 1, 1) - unix_epoch < days {
        year = year + 1;
    }
    year = year -1;
    let mut month = 1;
    while daycounts_fairfield(year, month, 1) - unix_epoch < days {
        month = month + 1;
    }
    month = month -1;
    let diff_days = daycounts_fairfield(year, month, 1)-unix_epoch;
    
    (year, month, days-diff_days+1)
}
以上の関数を用いて、タイムスタンプを生成する関数は、こうなる。
fn timestamp_now() -> String {
    let unixtime = now_from_unix_epoch();

    let (days, hour, minute, second) = counts_day_from_sec(unixtime, 9.0);
    let (year, month, day) = days_to_date(days);
    format!("{:04}/{:02}/{:02} {:02}:{:02}:{:02}", 
            year, month, day, hour, minute, second.floor() as u32)
}      
最後は、メイン関数。
fn main() {
    let s = timestamp_now();
    println!("{}", s);
}
以上をtimestamp.rsというファイルに記述したら、
rustc timestamp.rs
でコンパイルでき、timestamp.exeが生成される。

Rustは、f64とu32の除算は定義されていないなど、 どの型で計算するかをしっかり考えておかないといけない。 ただ、コンパイラのエラーメッセージが非常に親切で、メッセージを読むのが楽しい。 また、定数は大文字にしなさいや、変数名をスネークケースにしなさいなど記述についても指示が出た。

2020年8月1日土曜日

Windows10 Rust(mingw)をインストール

Windows10にRustをインストールしてみた。 MSYS2を用いてインストールしたgcc環境があるので、 MSVC版ではなく,こちらを利用したい。

今は、rustupを利用してインストール管理をするようである。 Windows では、rustup-init.exeをダウンロードしてインストールするようだ。 Rustの公式ページのInstallからダウンロードできる。 64ビット環境なので、64-BITのrustup-init.exeをダウンロードし、実行した。

1) Proceed with installation (default)
2) Customize installation
3) Cancel installation
と尋ねられるので、(2)を選ぶ。 もしVisual Studioを使っているなら、defaultでよいのだろう。

Default host triple?と尋ねられるので、こちらで x86_64_pc-windows-gnu
を入力した。結局、

  
default host triple: x86_64-pc-windows-gnu
default toolchain: stable
profile: default
modify PATH variable: yes
として、再び最初のメニューが現れるので、
(1) Proceed with installation (default)
を選ぶと、無事にインストールされた。
ユーザーのホームフォルダの.cargoの中にインストールされた。

とりあえずfizzbuzzを書いて試してみる。

fn fizzbuzz(i:u32) -> String {
    if i%15==0 {
        "FizzBuzz".to_string()
    } else if i%3==0 {
        "Fizz".to_string()
    } else if i%5==0 {
        "Buzz".to_string()
    } else {
        i.to_string()
    }
}

fn main() {
    for i in 1..101 {
        println!("{}", fizzbuzz(i));
    }
}          
fizzbuzz.rsというファイルに保存したら、
rustc fizzbuzz.rs
でコンパイルリンクされfizzbuzz.exeが生成された。