coLinux日記

coLinuxはフリーソフトを種として、よろずのシステムとぞなれりける。

Raspberry Pi に Python 3.12.6 をインストールする

2024-09-20 15:40:08 | Python
前回 Raspberry Pi の Pi OS も再インストールできたので、Python3 をインストールしてみます。

Python 3.12.6 が、日本時間 2024-09-07 にリリースされていました。

3.12.6 は最新のメンテナンス リリースで、3.12.5 以降の約 90 のバグ修正、ビルドの改善、ドキュメントの変更が含まれています。これは、次のセキュリティ問題に対処するための緊急リリースです。

早速ダウンロードしてみましょう。

$ wget https://www.python.org/ftp/python/3.12.6/Python-3.12.6.tar.xz

PGP署名ファイルもダウンロードします。

$ wget https://www.python.org/ftp/python/3.12.6/Python-3.12.6.tar.xz.asc

壊れたOSのユーザファイルは元に戻してあり、公開鍵はすでにインポートしているので、確認します。

$ gpg --verify Python-3.12.6.tar.xz.asc
gpg: assuming signed data in 'Python-3.12.6.tar.xz'
gpg: Signature made Fri 06 Sep 2024 21:33:01 BST
gpg:        using RSA key 7169605F62C751356D054A26A821E680E5FA6305
gpg: Good signature from "Thomas Wouters <thomas@python.org>" [unknown]
gpg:        aka "Thomas Wouters <thomas@xs4all.nl>" [unknown]
gpg:        aka "Thomas Wouters <twouters@google.com>" [unknown]
gpg:        aka "Thomas Wouters <thomas.wouters.prive@gmail.com>" [unknown]
gpg:        aka "Thomas Wouters <thomaswout@gmail.com>" [unknown]
gpg: WARNING: This key is not certified with a trusted signature!
gpg:     There is no indication that the signature belongs to the owner.
Primary key fingerprint: 7169 605F 62C7 5135 6D05 4A26 A821 E680 E5FA 6305
$


早速、以前行ったこちらのようにインストールしてみます。
https://blog.goo.ne.jp/espiya/e/fdf200d42183170e14bd374987749a7d

まずは、関連パッケージを apt でインストールします。

# apt install libncurses-dev libreadline-dev libssl-dev libssh-dev
#
    ( libssh-dev は、念のため )

# apt install libsqlite3-dev libbz2-dev libffi-dev libgdbm-dev liblzma-dev tcl tcl-dev tk tk-dev uuid-dev zlib1g-dev
#

早速 make してみましょう。

$ tar xvf Python-3.12.6.tar.xz
$ cd Python-3.12.6
$ ./configure --prefix=/usr/local/python --enable-optimizations  --with-readline --enable-shared
$ make
$


_dbm がないのは前回通りです。

make できたら、インストールします。インストール先の /usr/local/python は、無ければ生成してくれました。

# make install

Python3 を使うための環境設定は、 環境変数を export するところを python3.sh というファイルにして、Bash の場合次のように設定します。

$ cat python3.sh
export PATH=/usr/local/python/bin:$PATH
export LD_LIBRARY_PATH=/usr/local/python/lib
$

$ source python3.sh


早速実行してみました。

$ python3
Python 3.12.6 (main, Sep 14 2024, 16:22:55) [GCC 12.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.

>>>
$
$ pip3 --version
pip 24.2 from /usr/local/python/lib/python3.12/site-packages/pip (python 3.12)
$


これで、最新の Python3 がインストールできました。

壊れてしまったRaspberry Pi のシステムもほぼ元通りになり、10月に 3.13 がリリースされる予定なので、その準備もできましたね。
コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

Raspberry Pi、システム的な不具合をなおす。

2024-09-15 07:16:01 | Raspberry Pi
使っている Raspberry Pi で、 apt update を実行したら、基本的なライブラリ?が壊れたらしく、コマンドが動かなくなり、再度ログインできなくなりました。
お手上げですね。これでは Python3 も試せません。

しかたがないので、OSをインストールし直します。以下は大雑把なメモです。SSHD を起動して外からログインできるようにするのがとりあえずの目標ですね。

https://www.raspberrypi.com/software/operating-systems/
から、
Raspberry Pi OS (64-bit)/Raspberry Pi OS Lite
2024-07-04-raspias-bookworm-arm64-lite.img

を、Image Writer for Microsoft Windows のようなツールを使ってUSBメモリへコピーします。

本体にメモリを差し込んで、ディスプレイ、キーボード、マウス、ネットワークケーブルを繋いで、電源を入れてブートしてと、ホスト名を設定し、ユーザ名を入力してパスワードを入れてブートするとそのユーザ名でログインできるようになります。

ログインして、raspi-config で sshd を起動させます。ここは、専用ツールを使います。

# raspi-config

で、
3. Interface Options を選択して、
11. SSH を選択して、「Yes」を選ぶと

 The SSH server is enabled

になります。再起動が要求されるならそれに従って、他からログインできれば完了です。

一度シャットダウンして、すべてを外して、ネットワークケーブルだけ繋いで立ち上げれば一応動くようになりました。

今回は64ビット版ですね。

$ cat /etc/os-release
PRETTY_NAME="Debian GNU/Linux 12 (bookworm)"
NAME="Debian GNU/Linux"
VERSION_ID="12"
VERSION="12 (bookworm)"
VERSION_CODENAME=bookworm
ID=debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"
espiya@rasp4mb:~ $

このままだと、パスワード無しで sudo が実行出来てしまうので、

まず、root のパスワードを設定します。
$ sudo passwd root

確認するために root になります。
$ su

#

今回は、
/etc/sudoers.d/010_pi_nopasswd
の内容の行の先頭に # を付けてコメントにし、

# visudo
で、
%sudo ALL=(ALL:ALL)ALL
の行の先頭に # を付けてコメントしました。これは、/etc/sudoers ファイルを更新するのですね。

詳しく調べていませんが、一応これで設定は終了です。

古いメモリカードをUSBで接続すると、ファイルシステムは /dev/sda2 となって、これをマウントすれば読み取れました。

これで、Python環境(make したディレクトリとか)を復元しました。
cp コマンドに -Rp オプションを付けてコピーすればディレクトリ毎コピーできます。

apt も試してみました。

# apt update
......
# apt upgrade
......

無事にアップデートもできました。

次回は、再び Python3 をインストールしてみます。
コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

SimplePrograms で Python を学ぶ その21

2024-09-07 21:28:15 | Python
SimplePrograms - Python Wiki
https://wiki.python.org/moin/SimplePrograms

の 21番目のプログラムは、33行の数字当てゲームです。

import random

guesses_made = 0

name = input('Hello! What is your name?\n')

number = random.randint(1, 20)
print ('Well, {0}, I am thinking of a number between 1 and 20.'.format(name))

while guesses_made < 6:

    guess = int(input('Take a guess: '))

    guesses_made += 1

    if guess < number:
       print ('Your guess is too low.')

    if guess > number:
       print ('Your guess is too high.')

    if guess == number:
       break

if guess == number:
    print ('Good job, {0}! You guessed my number in {1} guesses!'.format(name, guesses_made))
else:
    print ('Nope. The number I was thinking of was {0}'.format(number))


例によって、prog-33.py というファイルにして実行してみます。

$ python3 prog-33.py
Hello! What is your name?
espiya
Well, espiya, I am thinking of a number between 1 and 20.
Take a guess: 5
Your guess is too low.
Take a guess: 10
Your guess is too high.
Take a guess: 8
Your guess is too high.
Take a guess: 6
Good job, espiya! You guessed my number in 4 guesses!
$


6回までに1から20までの数を当てるゲームですね。

6回で当てられないと、
Nope. The number I was thinking of was 6
$

となります。

さすがに最後のプログラムとなると新しい機能はほとんど使われていませんね。

その中で、random モジュールが使われています。
https://docs.python.org/ja/3/library/random.html#module-random

このモジュールでは様々な分布をもつ擬似乱数生成器を実装しています。

整数用に、ある範囲からの一様な選択があります。シーケンス用には、シーケンスからのランダムな要素の一様な選択、リストのランダムな置換をインプレースに生成する関数、順列を置換せずにランダムサンプリングする関数があります。

実数用としては、一様分布、正規分布 (ガウス分布)、対数正規分布、負の指数分布、ガンマおよびベータ分布を計算する関数があります。角度の分布を生成するにはフォン・ミーゼス分布が利用できます。

ほとんど全てのモジュール関数は、基礎となる関数 random() に依存します。この関数はランダムな浮動小数点数を半開区間 0.0 <= X < 1.0 内に一様に生成します。Python は中心となる乱数生成器としてメルセンヌツイスタを使います。これは 53 ビット精度の浮動小数点を生成し、周期は 2**19937-1 です。本体は C で実装されていて、高速でスレッドセーフです。メルセンヌツイスタは、現存する中で最も広範囲にテストされた乱数生成器のひとつです。しかしながら、メルセンヌツイスタは完全に決定論的であるため、全ての目的に合致しているわけではなく、暗号化の目的には全く向いていません。



以前、LINEのAIチャット君の紹介で出てきたように、random()の乱数生成方法はメルセンヌツイスタを使っているのですね。注意書きにもあるように、メルセンヌツイスタは決定論的なので、使用するシードに工夫が必要ですが、生成される乱数はOS提供の乱数に比べれば非常に良いと考えられるので、乱数が必要なプログラムでは十分使えますね。この中で、


random.randint(a, b)

a <= N <= b であるようなランダムな整数 N を返します。randrange(a, b+1) のエイリアスです。



を使って、1から20までの乱数を生成して答えとするわけです。

クイズなので、input() で入力を、print() で出力をするプログラムですね。
整数入力の時は、 int(input(.....)) と覚えておきます。

while ループ内の if 文ですが、elif や continue を使いたいと思う気がしますが、
SimplePrograms ではいずれも使っていませんでした。

さて、出力ですが、

https://docs.python.org/ja/3.8/tutorial/inputoutput.html#input-and-output
によると、


・ フォーマット済み文字列リテラル を使うには、開き引用符や三重の開き引用符の前に f あるいは F を付けて文字列を始めます。 この文字列の内側では、文字 { と文字 } の間に Python の式が書け、その式から変数やリテラル値が参照できます。

・ 文字列の str.format() メソッドは、もう少し手間がかかります。 ここでも { と } を使って変数に代入する場所の印を付けて、細かいフォーマットの指示を出せますが、フォーマットされる対象の情報を与える必要があります。

フォーマット済み文字リテラル (短くして f-string とも呼びます) では、文字列の頭に f か F を付け、式を {expression} と書くことで、 Python の式の値を文字列の中に入れ込めます。



これを、いつくか試してみます。

>>> a = 10
>>> b = 100
>>>
>>> print(f'A is {a}, B is {b}.')
A is 10, B is 100.
>>>
>>> print('A is {a00}, B is {b00}.'.format(a00=a, b00=b))
A is 10, B is 100.
>>>
>>> print('A is {0}, B is {1}.'.format(a, b))
A is 10, B is 100.
>>>
>>> print('A is {a}, B is {b}.'.format(a, b))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'a'
>>>
>>> print('A is {a}, B is {b}.'.format(a = a, b = b))
A is 10, B is 100.
>>>


エラーになる例は間違えそうなので、一番最後の例の形で覚えておくことにします。

SimplePrograms では、f-string が出てこなくて、str.format() のみ使っているので、
何かあるのかもしれませんね。

以上、SimplePrograms の21の各プログラムを見てきましたが、入門としてはちょっと変わった?機能を使うことがあり、これを Python プログラミングで使った方が良いという考え方があるような気がしました。特に入門時に docstring を使えるようにする(ちょっと大変と思うなら、生成AIを使う)ことは、プログラミングに有用だと感じました。

今後も何かあれば、Python について試して見たいと思います。
コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

SimplePrograms で Python を学ぶ その20

2024-09-01 09:54:16 | Python
SimplePrograms - Python Wiki
https://wiki.python.org/moin/SimplePrograms

の 20番目のプログラムは、 28行の2度目の8クイーン問題で、独自の例外(exception)の定義です。

BOARD_SIZE = 8

class BailOut(Exception):
    pass

def validate(queens):
    left = right = col = queens[-1]
    for r in reversed(queens[:-1]):
       left, right = left-1, right+1
       if r in (left, col, right):
          raise BailOut

def add_queen(queens):
    for i in range(BOARD_SIZE):
       test_queens = queens + [i]
       try:
          validate(test_queens)
          if len(test_queens) == BOARD_SIZE:
             return test_queens
          else:
             return add_queen(test_queens)
       except BailOut:
          pass
    raise BailOut

queens = add_queen([])
print (queens)
print ("\n".join(". "*q + "Q " + ". "*(BOARD_SIZE-q-1) for q in queens))


再び、8クイーン問題を扱うプログラムですが、答えは1つだけ表示されます。早速これを prog-28.py というファイルにして実行してみます。

$ python3 prog-28.py
[0, 4, 7, 5, 2, 6, 1, 3]
Q . . . . . . .
. . . . Q . . .
. . . . . . . Q
. . . . . Q . .
. . Q . . . . .
. . . . . . Q .
. Q . . . . . .
. . . Q . . . .
$


最初に、Google Gemini による解説を抜粋します。

ここから========>
### コードの解説

#### 定数と例外
* **BOARD_SIZE:** チェスボードのサイズを定義しています。このプログラムでは、8×8のチェスボードを想定しています。
* **BailOut:** 探索中に矛盾が生じた場合に発生させるカスタム例外です。

#### 関数
* **validate(queens):**
* 引数として、既に配置されたクイーンの列番号のリストを受け取ります。
* 新たに追加しようとしているクイーンと、既に配置されているクイーンが互いに攻撃できるかどうかを検証します。
* 攻撃できる場合は、BailOut例外を発生させます。
* **add_queen(queens):**
* 再帰的な関数で、チェスボードの次の行にクイーンを配置する場所を探索します。
* すべての行にクイーンが配置できたら、その配置のリストを返します。
* 配置できない場合は、BailOut例外を発生させます。

#### メインロジック
* **queens = add_queen([]):**
* 空のリストから始めて、add_queen関数で全てのクイーンを配置します。
* **print(queens):**
* 求められたクイーンの配置(列番号のリスト)を出力します。
* **print("\n".join(". "*q + "Q " + ". "*(BOARD_SIZE-q-1) for q in queens)):**
* 求められたクイーンの配置を、チェスボードの形で視覚的に表示します。"Q"がクイーンを表し、"."が空のマスを表します。

### プログラムの仕組み
1. **add_queen**関数は、チェスボードの最初の行から始めて、各行にクイーンを配置できるかどうかを順に試します。
2. **validate**関数は、新しいクイーンを追加するたびに、そのクイーンが他のクイーンと攻撃できるかどうかを検証します。
3. 攻撃できる場合は、**BailOut**例外が発生し、**add_queen**関数は別の配置を試します。
4. 全ての行にクイーンが配置できたら、その配置が一つ見つかったことになるので、探索を終了します。
5. もし、全ての可能性を試しても有効な配置が見つからなければ、**BailOut**例外が発生し、プログラムはエラーで終了します。

### より詳しく
* **再帰:** このプログラムでは、**add_queen**関数が自分自身を呼び出す再帰的な構造になっています。再帰は、問題をより小さな部分問題に分割し、それらを解決することで全体の問題を解決する手法です。
* **バックトラッキング:** 探索中に矛盾が生じたら、一つ前の状態に戻って別の選択肢を試す手法をバックトラッキングといいます。このプログラムでも、**BailOut**例外が発生した際に、一つ前の状態に戻って探索を続けることで、バックトラッキングが行われています。

ここまで========>

Gemini もこのように、プログラムの概要は教えてくれますね。気になるところを見ていきます。

まず、クラス BailOutの定義が、「カスタム例外」(独自の例外:your own exceptions)ですね。
https://docs.python.org/ja/3/tutorial/controlflow.html#pass-statements

pass 文は何もしません。 pass は、文を書くことが構文上要求されているが、プログラム上何の動作もする必要がない時に使われます:

これは最小のクラスを作るときによく使われる方法です:


ということで、ここで言う「最小のクラス」を定義しているようです。何もしないのが重要ですね。
これは、validate() 関数(基本的には前に出てきた18lines プログラムのunder_attack()関数と同じもの)の中で使われている、raise文
https://docs.python.org/ja/3/reference/simple_stmts.html#the-raise-statement

と関連しており、

raise は最初の式を、例外オブジェクトとして評価します。これは、 BaseException のサブクラスまたはインスタンスでなければなりません。クラスなら、例外インスタンスが必要なとき、クラスを無引数でインスタンス化することで得られます。

例外の 型 は例外インスタンスのクラスで、 値 はインスタンスそのものです。

となって、if 文の条件が真ならば、例外 BailOut が発生するのですね。

その例外を受けるものがないと、普通のエラーみたいになる?ので、validdate()を中で呼び出す、
add_queen()関数の定義の中で 8lines プログラムのように、try ~ except を使って、
この例外を処理するようです。

つまり、validate()で例外BailOutが発生すると except節が実行されて、何もせずにfor文の次の i が代入されて繰り返すようです。validate()で例外が発生しなければ、test_queens の長さが、
8になるまではadd_queen()が再帰的に呼ばれて、
8になったら test_queens を返す
ので、実行例のように最初に見つかった配置を返すのでしょう。

add_queen()の最後の raise 文は念のためのような気がします。これがないと返却値がないことになるので、その判定が必要になるからだと思います。というわけで、適当に簡略化すると、

class カスタム例外:
    ....

def func_test(....):
    for
       ...
       try:
            ...
       except カスタム例外:
            ...
    raise カスタム例外


となるのが、入門者が覚えた方が良い形でしょうか。

最後は、add_queen()で生成された解 queens を出力して、それを使ってジェネレータ式でチェス盤を出力するのですね。 改行文字を頭に付けるのが面白いですね。

join()の使い方をみるために少し試してみました。分かりやすくするために改行文字を"++"にしました。
まず、ジェネレータ式ではない場合です。

>>> q = 3
>>> print("++".join(". "*q + "Q " + ". "*(8-q-1)))
.++ ++.++ ++.++ ++Q++ ++.++ ++.++ ++.++ ++.++


join()の中の文字列「1文字ずつ」に"++"を付加するのですね。つまり単純化すると、

>>> print("++".join("ABCDE"))
A++B++C++D++E
>>>


です。

これをプログラムのようにジェネレータ式にすると、

>>> queens = [2,3,4,6]
>>> print("++".join(". "*q + "Q " + ". "*(8-q-1) for q in queens))
. . Q . . . . . ++. . . Q . . . . ++. . . . Q . . . ++. . . . . . Q .
>>>


join()の使い方と共に、この事例は覚えておいて損はなさそうです。
コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする