Python: 複数の文字列の共通する部分文字列をとりだす

今日は Python。要するに、’abcde’、’abcxz’、’ab-op’ という文字列から、共通する部分文字列 ‘ab’ をとりだしたい(ただし先頭から)。

探せばいいのがあるかと思ったけど、見つからないので書いた。こんなふうになった。

import itertools

def common_substring(*strings):
    def same_all(*args):
        piv = args[0]
        return all([piv == e for e in args[1:]])
    return ''.join([s[0] for s in itertools.takewhile(lambda x: same_all(*x), zip(*strings))])

試してみよう。

>>> s1 = 'abcde'
>>> s2 = 'abcyz'
>>> s3 = 'ab-op'
>>> common_substring(s1, s2, s3)
'ab'

日本語でもいける。

>>> common_substring('こんにちは', 'こんばんは', 'こんちは')
'こん'

可変長引数をとるので、文字列は何個あってもいい。

カテゴリー: Python | コメントする

Windows11にJDK17をインストールした

Java についてはもう何年も前から、ライセンスで有料化だとか、開発主体が Oracle から離れたとかいう話を聞いていて、部外者から見ると何がどうなってんだかわからない状態なんだけど、Java で書かなきゃいけなさそうな事案に遭遇したので調べてみた。

といっても、ググっても情報が新旧入り混じっててむしろ混乱した。

なんとなくわかったことは:

  • Java SE 17 が最新
  • コミュニティによって OpenJDK として開発されてて、Oracle はじめいろんなところからバイナリ配布されてるらしい
  • 以前はランタイムだけの JRE ってのもあったけど今はない。開発ツールを含んだ JDK だけ

くらいなとこか。

結局 Oracle の JDK に msi インストーラがあったのでこれをインストールした。

Windows 用のインストーラなので指示通りにクリックしていけばOK。試しにコンソールから実行してみるとこんな感じ。

[email protected]: Documents > javac -version
javac 17.0.1
[email protected]: Documents > java -version
java version "17.0.1" 2021-10-19 LTS
Java(TM) SE Runtime Environment (build 17.0.1+12-LTS-39)
Java HotSpot(TM) 64-Bit Server VM (build 17.0.1+12-LTS-39, mixed mode, sharing)

まぁ、何とかなるだろ。

カテゴリー: Java, Windows | コメントする

Python: ローカルネットワー上のプライベートなPyPIリポジトリからpoetry addする on Windows

一昨日、Windows 10 上に pypiserver で立てたプライベートリポジトリから pip コマンドでパッケージをインストールできたので、今日は Poetry が使えるか試してみた。

まずは pypi-server コマンドでサーバを起動してプライベートリポジトリを作っておく。

[email protected]: Documents > pypi-server -p 8080 ./py-packages

別のターミナルを開いて、Poetry で新しいプロジェクトを作って中に移動する。

[email protected]: Documents > poetry new py-sample
Created package py_sample in py-sample
[email protected]: Documents > cd py-sample

Poetry にプライベートリポジトリを登録する。

[email protected]: py-sample > poetry config repositories.local http://localhost:8080/simple/

リポジトリの名前が local で、その URL が http://localhost:8080/simple/ だ。

つづいて pyproject.toml ファイルにプライベートリポジトリを参照するように次を追記する。

[[tool.poetry.source]]
name = "local"
url = "http://localhost:8080/simple/"

これで準備は完了。poetry install や poetry add でパッケージをインストールできるはず。あと、キャッシュを削除しておくのを忘れずに(まだ直ってない)。今回は PyPI.org には公開してない、自作の outputdatareader っていうパッケージを追加してみた。

[email protected]: py-sample > poetry add outputdatareader
Using version ^0.1.0 for outputdatareader

Updating dependencies
Resolving dependencies...

Writing lock file

Package operations: 11 installs, 0 updates, 0 removals

  • Installing pyparsing (2.4.7)
  • Installing atomicwrites (1.4.0)
  • Installing attrs (21.2.0)
  • Installing colorama (0.4.4)
  • Installing more-itertools (8.10.0)
  • Installing packaging (21.0)
  • Installing pluggy (0.13.1)
  • Installing py (1.10.0)
  • Installing wcwidth (0.2.5)
  • Installing outputdatareader (0.1.0)
  • Installing pytest (5.4.3)

無事インストールできた。

ちなみに、プライベートリポジトリには outputdatareader パッケージしか置いてないから、ほかのパッケージは PyPI.org からインストールしてる。

サーバ側のターミナルにはこんなふうに出力されている。

127.0.0.1 - - [22/Oct/2021 22:41:31] "GET /simple/outputdatareader/ HTTP/1.1" 200 353
127.0.0.1 - - [22/Oct/2021 22:41:33] "GET /simple/outputdatareader/ HTTP/1.1" 200 353
127.0.0.1 - - [22/Oct/2021 22:41:36] "GET /simple/pyparsing/ HTTP/1.1" 303 0
127.0.0.1 - - [22/Oct/2021 22:41:42] "GET /simple/atomicwrites/ HTTP/1.1" 303 0
127.0.0.1 - - [22/Oct/2021 22:41:42] "GET /simple/packaging/ HTTP/1.1" 303 0
127.0.0.1 - - [22/Oct/2021 22:41:42] "GET /simple/more-itertools/ HTTP/1.1" 303 0
127.0.0.1 - - [22/Oct/2021 22:41:42] "GET /simple/py/ HTTP/1.1" 303 0
127.0.0.1 - - [22/Oct/2021 22:41:42] "GET /simple/attrs/ HTTP/1.1" 303 0
127.0.0.1 - - [22/Oct/2021 22:41:42] "GET /simple/pluggy/ HTTP/1.1" 303 0
127.0.0.1 - - [22/Oct/2021 22:41:42] "GET /simple/colorama/ HTTP/1.1" 303 0
127.0.0.1 - - [22/Oct/2021 22:41:42] "GET /simple/wcwidth/ HTTP/1.1" 303 0
127.0.0.1 - - [22/Oct/2021 22:41:48] "GET /simple/outputdatareader/ HTTP/1.1" 200 353
127.0.0.1 - - [22/Oct/2021 22:41:48] "GET /simple/pytest/ HTTP/1.1" 303 0
127.0.0.1 - - [22/Oct/2021 22:41:50] "GET /packages/outputdatareader-0.1.0-py3-none-any.whl HTTP/1.1" 200 2016

outputdatareader 以外のパッケージではステータスコードが 303 (See Other)になってる。つまりプライベートリポジトリには無いってことで、そうすると Poetry は PyPI.org に探しに行く。最後の行から、プライベートリポジトリからは outputdatareader-0.1.0-py3-none-any.whl ファイルだけがダウンロードされてるのがわかる。

というわけで、今日はここまで。

カテゴリー: Python, Windows | コメントする

SQLite3のデータベースファイルからSQLにダンプする

たいしたネタじゃないけど、ときどき必要になる割にいつも調べてる気がするのでメモしておく。

SQLite3 のデータベースは1つのファイルになってる。このデータベースの中身を SQL にダンプするには sqlite3 コマンドをつかって、次の2通りのやり方がある。

対話的インターフェイスでダンプする方法

データベースを開くと、コマンド入力待ち状態になる。

[email protected]:db$ sqlite3 production.sqlite3
SQLite version 3.11.0 2016-02-15 17:29:24
Enter ".help" for usage hints.
sqlite>

ここで .dump コマンドでダンプすることができるけど、このままだと画面に出力されてしまうので、先に .output コマンドで出力先をファイルに変更しておく。

sqlite> .output ./dump.sql

これでカレントディレクトリの dump.sql ファイルに出力されるようになる。そしたら .dump コマンド。

sqlite> .dump

引数なしだとデータベース内のすべてのテーブルをダンプする。特定のテーブルだけをダンプするには、そのテーブル名を引数に与えればいい。

終わったら .exit

sqlite> .exit

コマンドラインから直接ダンプする方法

パイプを使って sqlite3 コマンドにダンプを指示する .dump コマンドを流し込んでやればいい。デフォルトでは標準出力に書き出すので、ファイルにリダイレクトする。

[email protected]:db$ echo '.dump' | sqlite3 production.sqlite3 > dump2.sql

定期的にバックアップするような場合にはこっちのほうが便利。

カテゴリー: misc, Ubuntu | コメントする

Python: ローカルネットワー上のプライベートなPyPIリポジトリからインストールする on Windows

先月同じようなタイトルの記事を書いたけど……

pip コマンドの --find-links オプションを使えば、パッケージファイルを放り込んだディレクトリを指定するだけでインストールすることができた。のだけれど、poetry を使うときにはこの方法ではダメだった。結局のところ PyPI.org 相当のプレイべートなリポジトリサーバを立ててやる必要がある。

選択肢としては pypiserver っていうパッケージがあって、それは知ってたんだけど、設定とか面倒そうだと勝手に思ったので今までやってみなかった。ところが今日試してみたら存外に簡単にできたのでメモしておくことにする。記事のタイトルにもあるように環境は Windows。

pypiserver 自体は pip コマンドでインストールできる。

[email protected]: Documents > pip install pypiserver
Looking in links: http://nightschool/py-packages/
Collecting pypiserver
  Using cached pypiserver-1.4.2-py2.py3-none-any.whl (77 kB)
Installing collected packages: pypiserver
Successfully installed pypiserver-1.4.2

これで完了。以下のようにインストールされてるのが確認できる。

[email protected]: Documents > pip list | grep pypiserver
pypiserver                        1.4.2

つぎに、パッケージファイルを置いておくフォルダを作る。

[email protected]: Documents > mkdir py-packages

    Directory: C:\Users\takatoh\Documents

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d----          2021/10/19    20:32                py-packages

で、ここに自作のパッケージファイルを放り込んだ。

[email protected]: Documents > ls py-packages

    Directory: C:\Users\takatoh\Documents\py-packages

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a---          2021/10/17    18:51           4035 brs-0.8.1-py3-none-any.whl

あとは pypi-server コマンドで起動すれば準備は完了。

[email protected]: Documents > pypi-server -p 8080 ./py-packages

-p 8080 オプションでポートを、引数でパッケージファイルの入っているフォルダを指定している。

さて、別のコンソールを立ち上げて pip install してみる。--extra-index-url http://localhost:8080/simple/ オプションでローカルホストに立てた pypiserver の URL を指定している。

[email protected]: takatoh > pip install --extra-index-url http://localhost:8080/simple/ brs
Looking in indexes: https://pypi.org/simple, http://localhost:8080/simple/
Looking in links: http://nightschool/py-packages/
Collecting brs
  Downloading http://localhost:8080/packages/brs-0.8.1-py3-none-any.whl (4.0 kB)
Requirement already satisfied: click<9.0.0,>=8.0.1 in c:\users\takatoh\appdata\local\programs\python\python39\lib\site-packages (from brs) (8.0.1)
Requirement already satisfied: PyYAML<6.0.0,>=5.4.1 in c:\users\takatoh\appdata\local\programs\python\python39\lib\site-packages (from brs) (5.4.1)
Requirement already satisfied: requests<3.0.0,>=2.26.0 in c:\users\takatoh\appdata\local\programs\python\python39\lib\site-packages (from brs) (2.26.0)
Requirement already satisfied: colorama in c:\users\takatoh\appdata\local\programs\python\python39\lib\site-packages (from click<9.0.0,>=8.0.1->brs) (0.4.4)
Requirement already satisfied: idna<4,>=2.5 in c:\users\takatoh\appdata\local\programs\python\python39\lib\site-packages (from requests<3.0.0,>=2.26.0->brs) (3.2)
Requirement already satisfied: certifi>=2017.4.17 in c:\users\takatoh\appdata\local\programs\python\python39\lib\site-packages (from requests<3.0.0,>=2.26.0->brs) (2021.5.30)
Requirement already satisfied: urllib3<1.27,>=1.21.1 in c:\users\takatoh\appdata\local\programs\python\python39\lib\site-packages (from requests<3.0.0,>=2.26.0->brs) (1.26.7)
Requirement already satisfied: charset-normalizer~=2.0.0 in c:\users\takatoh\appdata\local\programs\python\python39\lib\site-packages (from requests<3.0.0,>=2.26.0->brs) (2.0.6)
Installing collected packages: brs
Successfully installed brs-0.8.1

Looking in indexes: で始まる行で、PyPI.org とローカルに立てた pypiserver を見に行ってるのがわかる。つづく Looking in links: で始まる行では、先日の記事で設定したパッケージファイルの置いてある場所を探しに行っている。結果として、ローカルの pypiserver からダウンロードしてインストールしてるのがわかる。

サーバ側にはこんなふうに出力されていた。

127.0.0.1 - - [19/Oct/2021 20:35:27] "GET /simple/ HTTP/1.1" 200 207
127.0.0.1 - - [19/Oct/2021 20:35:27] "GET /favicon.ico HTTP/1.1" 404 711
127.0.0.1 - - [19/Oct/2021 20:36:42] "GET /simple/brs/ HTTP/1.1" 200 301
127.0.0.1 - - [19/Oct/2021 20:36:45] "GET /packages/brs-0.8.1-py3-none-any.whl HTTP/1.1" 200 4035

というわけで、Windows でもローカルに pypiserver を立てるのは寒暖だということが分かった。

あとはこれをサービスとしてバックグラウンドで動かせれば、poetry からも使えるようになる(はず)。それはまた今度。

カテゴリー: Python, Windows | コメントする

Python for Windows: インターネット接続を制限された環境ではpoetryがつかえない

pipはつかえる

このあいだ、インターネット接続を制限された職場のネット環境でもpipを使う方法を見つけた、という記事を書いた。少し時間が開いてしまったけど、今日試してみた。結果は「pipはつかえる」だ。

検証のために、インストールしてあった Python をいったん削除(キャッシュやらなんやらも全部削除)して、インストールしなおした。まぁ、バージョンアップもかねて、ね。

[email protected]: Documents > python -V
Python 3.9.7

この状態ではパッケージは2つしかインストールされてない。

[email protected]: Documents > pip list
Package    Version
---------- -------
pip        21.2.3
setuptools 57.4.0

で、PyPI.org にアクセスせずローカルなネットワークで完結するよう、pip の設定ファイル %APPDATA%\Roming\pip\pip.ini を書いておく。

[global]
find-links = file://workpc/py-packages

[install]
find-links = file://workpc/py-packages
no-index = yes

[list]
no-index = yes

このあいだの記事に書いたように、--find-links オプションを指定する代わりにここに書いておく。ここでは file://workpc/py-packages を指定している。no-index = yes は PyPI.org を見に行かないようにする設定。これがないと繋がらない PyPI.org にアクセスしようとして時間を無駄にすることになる。

つぎは上の find-links で指定した共有フォルダを作る。といっても自分の PC にテキトーなフォルダを作って py-packages って名前で共有するだけだ。あとはあらかじめダウンロードしておいたパッケージファイルを放り込んでおく。

さて、これで準備は完了。試しに poetry をインストールしてみた。

[email protected]: Documents > pip install poetry
Looking in links: file://workpc/py-packages
Processing \\workpc\py-packages\poetry-1.1.11-py2.py3-none-any.whl
Processing \\workpc\py-packages\html5lib-1.1-py2.py3-none-any.whl
Processing \\workpc\py-packages\keyring-21.8.0-py3-none-any.whl
Processing \\workpc\py-packages\shellingham-1.4.0-py2.py3-none-any.whl
Processing \\workpc\py-packages\tomlkit-0.7.2-py2.py3-none-any.whl
Processing \\workpc\py-packages\clikit-0.6.2-py2.py3-none-any.whl
Processing \\workpc\py-packages\requests_toolbelt-0.9.1-py2.py3-none-any.whl
Processing \\workpc\py-packages\cleo-0.8.1-py2.py3-none-any.whl
Processing \\workpc\py-packages\poetry_core-1.0.7-py2.py3-none-any.whl
Processing \\workpc\py-packages\cachy-0.3.0-py2.py3-none-any.whl
Processing \\workpc\py-packages\requests-2.26.0-py2.py3-none-any.whl
Processing \\workpc\py-packages\virtualenv-20.8.1-py2.py3-none-any.whl
Processing \\workpc\py-packages\crashtest-0.3.1-py3-none-any.whl
Processing \\workpc\py-packages\pexpect-4.8.0-py2.py3-none-any.whl
Processing \\workpc\py-packages\cachecontrol-0.12.6-py2.py3-none-any.whl
Processing \\workpc\py-packages\pkginfo-1.7.1-py2.py3-none-any.whl
Processing \\workpc\py-packages\packaging-20.9-py2.py3-none-any.whl
Processing \\workpc\py-packages\msgpack-1.0.2-cp39-cp39-win_amd64.whl
Processing \\workpc\py-packages\lockfile-0.12.2-py2.py3-none-any.whl
Processing \\workpc\py-packages\pylev-1.4.0-py2.py3-none-any.whl
Processing \\workpc\py-packages\pastel-0.2.1-py2.py3-none-any.whl
Processing \\workpc\py-packages\webencodings-0.5.1-py2.py3-none-any.whl
Processing \\workpc\py-packages\six-1.16.0-py2.py3-none-any.whl
Processing \\workpc\py-packages\pywin32_ctypes-0.2.0-py2.py3-none-any.whl
Processing \\workpc\py-packages\pyparsing-2.4.7-py2.py3-none-any.whl
Processing \\workpc\py-packages\ptyprocess-0.7.0-py2.py3-none-any.whl
Processing \\workpc\py-packages\urllib3-1.26.7-py2.py3-none-any.whl
Processing \\workpc\py-packages\idna-3.2-py3-none-any.whl
Processing \\workpc\py-packages\charset_normalizer-2.0.6-py3-none-any.whl
Processing \\workpc\py-packages\certifi-2021.5.30-py2.py3-none-any.whl
Processing \\workpc\py-packages\filelock-3.3.0-py3-none-any.whl
Processing \\workpc\py-packages\backports.entry_points_selectable-1.1.0-py2.py3-none-any.whl
Processing \\workpc\py-packages\platformdirs-2.4.0-py3-none-any.whl
Processing \\workpc\py-packages\distlib-0.3.3-py2.py3-none-any.whl
Installing collected packages: urllib3, idna, charset-normalizer, certifi, requests, pylev, pastel, msgpack, crashtest, webencodings, six, pywin32-ctypes, pyparsing, ptyprocess, platformdirs, lockfile, filelock, distlib, clikit, cachecontrol, backports.entry-points-selectable, virtualenv, tomlkit, shellingham, requests-toolbelt, poetry-core, pkginfo, pexpect, packaging, keyring, html5lib, cleo, cachy, poetry
Successfully installed backports.entry-points-selectable-1.1.0 cachecontrol-0.12.6 cachy-0.3.0 certifi-2021.5.30 charset-normalizer-2.0.6 cleo-0.8.1 clikit-0.6.2 crashtest-0.3.1 distlib-0.3.3 filelock-3.3.0 html5lib-1.1 idna-3.2 keyring-21.8.0 lockfile-0.12.2 msgpack-1.0.2 packaging-20.9 pastel-0.2.1 pexpect-4.8.0 pkginfo-1.7.1 platformdirs-2.4.0 poetry-1.1.11 poetry-core-1.0.7 ptyprocess-0.7.0 pylev-1.4.0 pyparsing-2.4.7 pywin32-ctypes-0.2.0 requests-2.26.0 requests-toolbelt-0.9.1 shellingham-1.4.0 six-1.16.0 tomlkit-0.7.2 urllib3-1.26.7 virtualenv-20.8.1 webencodings-0.5.1

無事完了。ちゃんとインストールできてるのも確認できる。

[email protected]: Documents > pip list
Package                           Version
--------------------------------- ---------
backports.entry-points-selectable 1.1.0
CacheControl                      0.12.6
cachy                             0.3.0
certifi                           2021.5.30
charset-normalizer                2.0.6
cleo                              0.8.1
clikit                            0.6.2
crashtest                         0.3.1
distlib                           0.3.3
filelock                          3.3.0
html5lib                          1.1
idna                              3.2
keyring                           21.8.0
lockfile                          0.12.2
msgpack                           1.0.2
packaging                         20.9
pastel                            0.2.1
pexpect                           4.8.0
pip                               21.2.3
pkginfo                           1.7.1
platformdirs                      2.4.0
poetry                            1.1.11
poetry-core                       1.0.7
ptyprocess                        0.7.0
pylev                             1.4.0
pyparsing                         2.4.7
pywin32-ctypes                    0.2.0
requests                          2.26.0
requests-toolbelt                 0.9.1
setuptools                        57.4.0
shellingham                       1.4.0
six                               1.16.0
tomlkit                           0.7.2
urllib3                           1.26.7
virtualenv                        20.8.1
webencodings                      0.5.1

というわけで、PyPI.org に繋がらない環境でも pip がつかえるのが確認できた。まぁわかってたけどね。

poetryはつかえない

つぎはインストールしたばかりの poetry を試してみた。

[email protected]: Documents > poetry config virtualenvs.in-project true
[email protected]: Documents > poetry new py-sample
Created package py_sample in py-sample

できたプロジェクトフォルダに入って、click を追加してみた。すると:

[email protected]: Documents > cd py-sample
[email protected]: py-sample > poetry add click
Creating virtualenv py-sample in C:\Users\username\Documents\py-sample\.venv

  ConnectionError

  HTTPSConnectionPool(host='pypi.org', port=443): Max retries exceeded with url: /pypi/click/json (Caused by NewConnectionError('<urllib3.connection.HTTPSConnection object at 0x0000020637A223D0>: Failed to establish a new connection: [WinError 10060] 接続済みの呼び出し 先が一定の時間を過ぎても正しく応答しなかったため、接続できませんでした。または接続済みのホストが応答しなかったため、確立された接続は失敗しました。'))

  at ~\AppData\Local\Programs\Python\Python39\lib\site-packages\requests\adapters.py:516 in send
      512│             if isinstance(e.reason, _SSLError):
      513│                 # This branch is for urllib3 v1.22 and later.
      514│                 raise SSLError(e, request=request)
      515│
    → 516│             raise ConnectionError(e, request=request)
      517│
      518│         except ClosedPoolError as e:
      519│             raise ConnectionError(e, request=request)
      520│

こんなエラーに。そうすんなりとは行ってくれないか。

ググってみると、Poetry の日本語ドキュメントのページを見つけた。これによると pyproject.toml ファイルを編集してプライベートなリポジトリを追加できるようなので、こんなふうに追記した。

[[tool.poetry.source]]
name = "private"
url = "file://workpc/py-packages/"

さっきの共有フォルダを見に行ってくれることを期待して書いたんだけど、結果は次の通り:

[email protected]: py-sample > poetry add click

  InvalidSchema

  No connection adapters were found for 'file://workpc/py-packages/click/'

  at ~\AppData\Local\Programs\Python\Python39\lib\site-packages\requests\sessions.py:742 in get_adapter
      738│             if url.lower().startswith(prefix.lower()):
      739│                 return adapter
      740│
      741│         # Nothing matches :-/
    → 742│         raise InvalidSchema("No connection adapters were found for {!r}".format(url))
      743│
      744│     def close(self):
      745│         """Closes all adapters and as such the session"""
      746│         for v in self.adapters.values():

違うエラーを吐いた。どうやら PyPI.org の代わりに指定したプライベートなリポジトリを探しに行ってはくれてるようだけど、file: スキーマをサポートしてないようだ。ドキュメントを見る限りでは、プライベートなリポジトリとはいっても PyPI.org 相当の機能が必要で、パッケージファイルが置いてあればいいというわけではないらしい。ということは pipiserver を立てるしかないのか。

残念な結果に終わった。

カテゴリー: Python, Windows | コメントする

Python for Windows: poetryの挙動がおかしい

最近 Python をバージョンアップしたら、poetry の挙動がおかしい。poetry addpoetry install を実行して仮想環境にパッケージをインストールしようとしてもエラーを吐く。正確に言うとバージョンアップのせいなのかどうかはよくわからないのだけど、ほかに思い当たることもないんだ。

順を追ってみてみよう。Python と poetry のバージョンから。どちらも最新版。

[email protected]: w > python -V
Python 3.9.7
[email protected]: w > poetry -V
Poetry version 1.1.10

さて、まずは poetry new で新しいプロジェクトを作る。

[email protected]: w > poetry new py-sample
Created package py_sample in py-sample

で、できたプロジェクトのフォルダに入って poetry add する。今回はよく使う click を追加してみた。

[email protected]: w > cd py-sample
[email protected]: py-sample > poetry add click
Creating virtualenv py-sample in C:\Users\takatoh\Documents\w\py-sample\.venv
Using version ^8.0.1 for click

Updating dependencies
Resolving dependencies...

Writing lock file

Package operations: 11 installs, 0 updates, 0 removals

  • Installing pyparsing (2.4.7)
  • Installing atomicwrites (1.4.0)
  • Installing attrs (21.2.0)
  • Installing colorama (0.4.4)
  • Installing more-itertools (8.10.0)
  • Installing packaging (21.0)
  • Installing pluggy (0.13.1)
  • Installing py (1.10.0)
  • Installing wcwidth (0.2.5)
  • Installing click (8.0.1)
  • Installing pytest (5.4.3)

click のほかに仮想環境で使うパッケージもあわせて正常にインストールできた。

つぎに、いったん上のフォルダに移動して、別の新しいプロジェクトを作る。

[email protected]: py-sample > cd ..
[email protected]: w > poetry new py-sample-2
Created package py_sample_2 in py-sample-2

今できたほうのフォルダに入って、さっきと同じように poetry add で click を追加してみる。すると:

[email protected]: w > cd py-sample-2
[email protected]: py-sample-2 > poetry add click
Creating virtualenv py-sample-2 in C:\Users\takatoh\Documents\w\py-sample-2\.venv
Using version ^8.0.1 for click

Updating dependencies
Resolving dependencies...

Writing lock file

Package operations: 11 installs, 0 updates, 0 removals

  • Installing pyparsing (2.4.7)

  ValueError

  File \C:\Users\takatoh\AppData\Local\pypoetry\Cache\artifacts\92\0f\cf\effdcd5d76a6186df0969f85b3b030284ff8058936d5016540b5258ea3\pyparsing-2.4.7-py2.py3-none-any.whl does not exist

  at ~\AppData\Local\Programs\Python\Python39\lib\site-packages\poetry\core\packages\file_dependency.py:40 in __init__
       36│             except FileNotFoundError:
       37│                 raise ValueError("Directory {} does not exist".format(self._path))
       38│
       39│         if not self._full_path.exists():
    →  40│             raise ValueError("File {} does not exist".format(self._path))
       41│
       42│         if self._full_path.is_dir():
       43│             raise ValueError("{} is a directory, expected a file".format(self._path))
       44│


Failed to add packages, reverting the pyproject.toml file to its original content.

こんなふうにエラーになる。追加しようとした click じゃなくて仮想環境に必要な pyparsing っていうパッケージをインストールしようとしたところでエラーになってるのがわかる。poetry は一度インストールに使ったファイルはキャッシュしてて、このエラーはキャッシュしてるはずのファイル(\C:\Users\takatoh\AppData\Local\pypoetry\Cache\artifacts\92\0f\cf\effdcd5d76a6186df0969f85b3b030284ff8058936d5016540b5258ea3\pyparsing-2.4.7-py2.py3-none-any.whl)が見つからない、と言っている(ValueError の後に続く部分)。

ところが、ファイルはちゃんと存在する。

[email protected]: w > tree C:\Users\takatoh\AppData\Local\pypoetry\Cache\artifacts /F
フォルダー パスの一覧
ボリューム シリアル番号は 00000062 681C:8AA1 です
C:\USERS\TAKATOH\APPDATA\LOCAL\PYPOETRY\CACHE\ARTIFACTS
├─29
│  └─58
│      └─fc
│          └─ed8b7451d3ef91a6465024f5656141da996e7aafd4d41a1659629a75e7
│                  pluggy-0.13.1-py2.py3-none-any.whl
│
├─3d
│  └─af
│      └─11
│          └─94d692f8e0bf0791d76d42d8d257be6c7d2cba22ca4f745856c83286e9
│                  more_itertools-8.10.0-py3-none-any.whl
│
├─60
│  └─79
│      └─0b
│          └─c48bd9c2a989aa8b1eb7a67cd02b053c10734f2e4e5665f7995f09999c
│                  py-1.10.0-py2.py3-none-any.whl
│
├─6f
│  └─a9
│      └─ee
│          └─569c37f69a8c365ee41d2340aeac0214ee8c0086b8d8db43a21545204b
│                  attrs-21.2.0-py2.py3-none-any.whl
│
├─7d
│  └─f4
│      └─60
│          └─0737157bb9711fec72c70dff523aa54491eef317e0d586cf5388ff0908
│                  wcwidth-0.2.5-py2.py3-none-any.whl
│
├─92
│  └─0f
│      └─cf
│          └─effdcd5d76a6186df0969f85b3b030284ff8058936d5016540b5258ea3
│                  pyparsing-2.4.7-py2.py3-none-any.whl
│
├─9e
│  └─b3
│      └─11
│          └─7d87ac44fdb2d557301f1f4086a37c080d1482a98751abe7cdbabbad26
│                  colorama-0.4.4-py2.py3-none-any.whl
│
├─ae
│  └─32
│      └─83
│          └─e159324c1bd58177322f4e45f598d500fe22544bff20f53f55cf749da8
│                  click-8.0.1-py3-none-any.whl
│
├─b7
│  └─99
│      └─9c
│          └─c8ddc18c8225c740fc2ae6d503da3f93d5dddaf04afac3da460afacbc6
│                  atomicwrites-1.4.0-py2.py3-none-any.whl
│
├─e4
│  └─88
│      └─dd
│          └─3dbff42e3c4462dc3d027f5024025571166cb35edee215ce93852a968c
│                  pytest-5.4.3-py3-none-any.whl
│
└─f9
    └─4f
        └─09
            └─c91a145b26102e014fd6e33bd8c7b87306c8e1d4a771158f34dd13210e
                    packaging-21.0-py3-none-any.whl

pyparsing はなかほどに出力されてるね。なのに見つからないってどういうことさ。

さて、poetry の挙動がおかしいのはこれだけじゃない。というかこれから本番というか。

存在するのに見つからないっていうキャッシュをフォルダごと削除してやると、今度はインストールがうまくいく。まず削除。

[email protected]: w > rm C:\Users\takatoh\AppData\Local\pypoetry\Cache\artifacts -Recurse -Force

これで削除できてる。

[email protected]: w > tree C:\Users\takatoh\AppData\Local\pypoetry\Cache\artifacts /F
フォルダー パスの一覧
ボリューム シリアル番号は 00000066 681C:8AA1 です
C:\USERS\TAKATOH\APPDATA\LOCAL\PYPOETRY\CACHE\ARTIFACTS
無効なパスです - \USERS\TAKATOH\APPDATA\LOCAL\PYPOETRY\CACHE\ARTIFACTS
サブフォルダーは存在しません

で、あらためて poetry add click

[email protected]: w > cd py-sample-2
[email protected]: py-sample-2 > poetry add click
Using version ^8.0.1 for click

Updating dependencies
Resolving dependencies...

Package operations: 11 installs, 0 updates, 0 removals

  • Installing pyparsing (2.4.7)
  • Installing atomicwrites (1.4.0)
  • Installing attrs (21.2.0)
  • Installing colorama (0.4.4)
  • Installing more-itertools (8.10.0)
  • Installing packaging (21.0)
  • Installing pluggy (0.13.1)
  • Installing py (1.10.0)
  • Installing wcwidth (0.2.5)
  • Installing click (8.0.1)
  • Installing pytest (5.4.3)

ほら、ちゃんとインストールできた。どういうことだよ!

カテゴリー: Python, Windows | 3件のコメント

Python: pipでローカルネットワー上のプライベートなリポジトリからインストールする

仕事で使うちょっとしたツール(大抵はテキスト処理のツール)を Python で書いたりしてるんだけど、一つ不便なことがある。職場のネットワークから PyPI にアクセスできないんだ。

まぁ、セキュリティだの何だの考えるとインターネットへのアクセスを制限するのもわからないではない。

幸いブラウザでは繋がるので、ファイルを一つずつダウンロードしてからインストールすることは可能で、今までそうやってたんだけど不便なことこの上ない。パッケージがファイル一つで済むならまだいいんだけど、他のパッケージに依存してたりすると、正直やる気が失せてくるし、同僚に使ってもらおうというときにもハードルが高い。

さて、今日になって pip install コマンドの --find-links オプションでパッケージ置き場の URL を指定できることを知った。pypiserver みたいな PyPI クローンのサーバじゃなくて、ディレクトリにパッケージファイルを置いておくだけでいい。

早速、自宅の HTTP サーバにディレクトリを公開して試してみた。こんな感じ。

[email protected]:~$ pip install filtre --find-links http://nightschool/py-packages/ --trusted-host nightschool
Looking in links: http://nightschool/py-packages/
Collecting filtre
  Downloading http://nightschool/py-packages/filtre-0.1.0-py3-none-any.whl (1.9 kB)
Installing collected packages: filtre
Successfully installed filtre-0.1.0

http://nightschool/py-packages/ がパッケージファイルを置いてあるディレクトリの URL。--trusted-host nightschool オプションを指定してるのは HTTPS じゃなくて HTTP だから。filtre ってのは自作のパッケージね。

さらに、Windows なら file: スキーマでも行ける。上のディレクトリは Samba で共有フォルダにしてあって file://nightschool/shared/py-packages/ でアクセスできるので、こうすればいい。

[email protected]: Documents > pip install filtre --find-links file://nightschool/shared/py-packages/ --user
Looking in links: file://nightschool/shared/py-packages/
Processing \\nightschool\shared\py-packages\filtre-0.1.0-py3-none-any.whl
Installing collected packages: filtre
Successfully installed filtre-0.1.0

やぁ、これでだいぶ楽になるぞ。

ちなみに、パッケージファイルをダウンロード(インストールじゃなくて)するには pip download コマンドを使えば依存パッケージも含めてダウンロードしてくれる。使いそうなパッケージを自宅でダウンロードしたら、職場に持っていってまとめて適当な共有フォルダに放り込んでおけばいい。

[追記]

pip install コマンドの --find-links オプションや --trusted-host オプションは、pip の設定ファイルに書いておけばいちいち指定しなくてもいい。こんな感じ。

[install]
find-links = http://nightschool/py-packages/
trusted-host = nightschool

pip の設定ファイルは、Linux なら ~/.conf/pip/pip.conf、Windows なら %APPDATA%\pip\pip.ini。

カテゴリー: Python | コメントする

MediaWikiにYouTubeの動画を埋め込む

ローカルネットワーク上で使ってる MediaWiki に YouTube の動画を埋め込みたいと思って調べたら、そのまんま、YouTube という名前の拡張機能があった。マニュアルに使い方が載ってる。

これを使うことにする。

環境

  • Ubuntu server 20.04 LTS
  • Docker 20.10.8
  • docker-compose 1.25.5
  • MediaWiki 1.35.0

MediaWiki は Docker コンテナ上で動いていて、これは dockerhub から取ってきた公式のイメージを利用してる。

拡張機能のダウンロードとインストール

拡張機能は、上のリンクからたどってダウンロードした。YouTube-REL1_36-c352d8c.tar.gz っていうファイル名だった。

マニュアルによると、これを MediaWiki のディレクトリにある extensions/ ディレクトリに置けばいい。コンテナの中に入って確認すると、(コンテナ内の)/var/www/html/extensions/ に置けばいいことがわかった。

とはいえ、コンテナ内に置く必要はなくて、外(つまりホスト側)に置いてボリュームをマウントすればいい。実際、LocalSettings.php ファイルなんかもそうなっていて、~/docker-environments/wiki/ 以下に置いてある。

というわけで、ここに extensions/ ディレクトリを作って、YouTube 拡張機能を配置する。

$ cd ~/docker-environments/wiki
$ mkdir extensions
$ cd extensions
$ tar xzvf ~/YouTube-REL1_36-c352d8c.tar.gz

これで extensions/ ディレクトリの下に YouTube/ ディレクトリができる。

つぎに、MediaWiki の設定ファイル LocalSettings.php に1行書き加える。

wfLoadExtension('YouTube');

YouTube っていう拡張機能を読み込む設定だ。MediaWiki についてはこれで終わり。

Dockerコンテナの設定と再起動

拡張機能自体はコンテナの外に置いてあるので、ボリュームとしてマウントする。docker-compose.yml ファイルの volumes セクションに書き加える。

      - /home/takatoh/docker-environments/wiki/extensions/YouTube:/var/www/html/extensions/YouTube

最後にコンテナを起動し直して終わり。

$ docker-compose restart wiki

確認

実際に MediaWiki のページに YouTube の動画を埋め込めることを確認した。楽なもんだね。

カテゴリー: misc | コメントする

JavaScript:連番の配列を作る – あるいはJavaScriptの奇妙な仕様

JavaScript で連番の整数を要素に持つ配列を作る方法はいくつも考えられるだろうけど、こんなのを見つけた(見つけたコードそのままじゃなくて、少し整理してある)。

const initArray = (n) => [...Array(n)].map((_, i) => i);

いささかトリッキーだと思うけど、まっさきに思い浮かぶであろう for ループを使うよりも簡潔にかけている。もちろん、期待通りに動く。

> initArray(5);
[ 0, 1, 2, 3, 4 ]

自分のメモのために説明しておくと、Array(n) で要素 n 個の配列をつくり、スプレッド構文を使って別の配列リテラルの中に埋め込む。で、map メソッドを呼び出して、各要素をそのインデックス値に置き換える。結果的に 0 からはじまり n 個の連番をもつ配列が出来上がる。

さて、トリッキーだと思うのは、コンストラクタでつくった配列 Array(n) をわざわざスプレッド構文を使って別の配列リテラルに埋め込むところ [...Array(n)] だ。だけどこれがないと期待通りに動かない。

> Array(5).map((_, i) => i);
[ <5 empty items> ]

<5 empty items> ってなんだ。そりゃ初期化してないから空の配列なんだろうけど、長さ(要素数)は 5 なんでしょ?

> Array(5).length;
5

いままで使ったことがなかったので知らなかったけど、配列をコンストラクタ Array() でつくると、長さはあるけど何の値も入ってない、まさに空の配列が返ってくる。

> Array(5);
[ <5 empty items> ]

この「空(から)」は undefined でも null でもない。この配列にインデックスを使ってアクセスすると undefined が返ってくる。

> const a = Array(5);
undefined
> a[3];
undefined
> a[3] == undefined;
true

なら undefined が5個入った配列と等しいのかというとそれも違う。

> a == [undefined, undefined, undefined, undefined, undefined];
false

さらにいえば、リテラルでつくったから配列とも違う。

> a == [];
false

わけがわからないよ。

カテゴリー: JavaScript | コメントする