Nx-WorkspaceでAngular+NestJSのプロジェクトを構築する

Nx Workspaceを使ってAngular+NestJSのプロジェクトを作成します。

Nx Workspaceとは?

Nx Workspaceとは、Angular CLIを使用して開発する際に、複数のアプリケーションやライブラリを一元管理するツールです。Nx WorkspaceはAngular CLIだけでなく、ReactやNestJSなども管理することができます。

今回はフロントエンドとしてAngularを使用し、バックエンドとしてNestJSを使用してみます。

Angular CLIをインストールする

まずはAngular CLIをインストールします。

Node.jsは執筆時点のLTS版を使用しています。

$ node -v
v18.14.0
$ npm -v
9.4.2

通常の手順どおりにAngular CLIをインストールします。すでにインストール済みの場合はこの手順はスキップしてください。

$ npm install -g @angular/cli
$ ng version

     _                      _                 ____ _     ___
    / \   _ __   __ _ _   _| | __ _ _ __     / ___| |   |_ _|
   / △ \ | '_ \ / _` | | | | |/ _` | '__|   | |   | |    | |
  / ___ \| | | | (_| | |_| | | (_| | |      | |___| |___ | |
 /_/   \_\_| |_|\__, |\__,_|_|\__,_|_|       \____|_____|___|
                |___/


Angular CLI: 15.1.5
Node: 18.14.0
Package Manager: npm 9.4.2
OS: darwin arm64

Angular:
...

Package                      Version
------------------------------------------------------
@angular-devkit/architect    0.1501.5 (cli-only)
@angular-devkit/core         15.1.5 (cli-only)
@angular-devkit/schematics   15.1.5 (cli-only)
@schematics/angular          15.1.5 (cli-only)

次に@nwrl/schematicsをインストールします。@nwrl/schematicsは新しいアプリケーションやライブラリを生成するためのツールです。

$ npm install -g @nrwl/schematics

警告がかなり表示されるかもしれませんが、気にせずインストールしてください。

プロジェクトを作成する

create-nx-workspaceを使ってプロジェクトを作成します。後からアプリケーションを追加するので、--preset=emptyを指定して空のプロジェクトを作成します。

執筆時点では1回だけ質問されますが、ここではNoで回答します。

$ npx create-nx-workspace@latest demo-app --preset=empty
$ cd demo-app

以降の操作は作成したプロジェクト内で行います。

フロントエンドの作成

Angularをインストールし、フロントエンドアプリケーションを作成します。

まずは、@nrwl/angularパッケージをインストールします。

$ npm install -D @nrwl/angular

次にAngularのアプリケーションを作成します。nx generate @nrwl/angular:appコマンドを使うことでAngularのアプリケーションを作成できます。

$ npx nx generate @nrwl/angular:app frontend --routing

インストールが完了したら、サーバーを起動して動作確認してみましょう。

$ npx nx serve frontend

Angularの標準的な画面とは異なりますが、http://localhost:4200/にアクセスし、下記のような画面が表示されればサーバーが問題なく起動しています。

バックエンドの作成

次にバックエンドを作成します。基本的な流れは先ほどと同じです。

まずは@nrwl/nestパッケージをインストールします。

$ npm install -D @nrwl/nest

nx generate @nrwl/nest:appコマンドでバックエンドアプリケーションを作成します。

$ npx nx generate @nrwl/nest:app backend --frontendProject frontend

>  NX  Generating @nrwl/nest:application

UPDATE package.json
CREATE apps/backend/src/app/.gitkeep
CREATE apps/backend/src/assets/.gitkeep
CREATE apps/backend/src/main.ts
CREATE apps/backend/tsconfig.app.json
CREATE apps/backend/tsconfig.json
CREATE apps/backend/webpack.config.js
CREATE apps/backend/project.json
CREATE apps/backend/.eslintrc.json
CREATE apps/backend/jest.config.ts
CREATE apps/backend/tsconfig.spec.json
CREATE apps/backend-e2e/project.json
CREATE apps/backend-e2e/jest.config.ts
CREATE apps/backend-e2e/src/backend/backend.spec.ts
CREATE apps/backend-e2e/src/support/global-setup.ts
CREATE apps/backend-e2e/src/support/global-teardown.ts
CREATE apps/backend-e2e/src/support/test-setup.ts
CREATE apps/backend-e2e/tsconfig.json
CREATE apps/backend-e2e/tsconfig.spec.json
CREATE apps/backend-e2e/.eslintrc.json
CREATE apps/frontend/proxy.conf.json
UPDATE apps/frontend/project.json
CREATE apps/backend/src/app/app.controller.spec.ts
CREATE apps/backend/src/app/app.controller.ts
CREATE apps/backend/src/app/app.module.ts
CREATE apps/backend/src/app/app.service.spec.ts
CREATE apps/backend/src/app/app.service.ts

added 27 packages, changed 1 package, and audited 1462 packages in 13s

180 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities

こちらもサーバーを起動し、動作確認をしてみます。

$ npx nx serve backend

http://localhost:3333/apiにアクセスし、以下のようにメッセージが返ってくれば正常にサーバーが起動しています。

データバージョン管理ツール「DVC」を導入する

データバージョン管理ツールのDVCを導入し、データセットをDVCで管理する方法について説明します。

DVCのインストールと初期化

DVCをインストールして初期化を行います。

DVCはpipコマンドまたはcondaコマンドでインストールします。

$ pip install dvc
または
$ conda install -c conda-forge dvc

次にDVCの初期化を行いますが、Gitの初期化を行なっていない場合は先にgit initを実行してください。

プロジェクトルートで以下のコマンドを実行します。

$ dvc init
Initialized DVC repository.

You can now commit the changes to git.

+---------------------------------------------------------------------+
|                                                                     |
|        DVC has enabled anonymous aggregate usage analytics.         |
|     Read the analytics documentation (and how to opt-out) here:     |
|             <https://dvc.org/doc/user-guide/analytics>              |
|                                                                     |
+---------------------------------------------------------------------+

What's next?
------------
- Check out the documentation: <https://dvc.org/doc>
- Get help and share ideas: <https://dvc.org/chat>
- Star us on GitHub: <https://github.com/iterative/dvc>

コマンドを実行すると、.dvcと.dvcignoreが作成されます。

一旦変更をコミットしましょう。

データセットの管理先を設定する(リモートストレージ)

機械学習やディープラーニングで使用するデータセットはサイズが非常に大きく、Gitリポジトリで管理するのに適していません。

ここではAmazon S3にデータセットを保存する手順で説明します。S3が使用できなくて、NASやファイルサーバーがある場合はそちらを使っていただいても構いませんし、大容量ディスクがPCに搭載されていればそちらも選択しても構いません。

$ aws configure
AWS Access Key ID [None]: XXXXXXXXXXXXXXXXXXXX
AWS Secret Access Key [None]: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Default region name [None]: ap-northeast-1
Default output format [None]: json

AmazonS3FullAccessポリシーをもったユーザーをAWS CLIに設定します。

またアップロードするS3バケットを用意してください(アクセス範囲には十分ご注意ください)。

$ dvc remote add -d main s3://datascience-dvc-remote-storage
Setting 'main' as a default remote.

リモートストレージを設定すると、.dvc/configに設定が書き込まれます。

[core]
    remote = main
['remote "main"']
    url = s3://datascience-dvc-remote-storage

リモートストレージを追加したら変更をコミットしておきましょう。

データセットを追加する

設定できたのでデータセットを追加してみます。ここではKaggleのTitanicのデータセットを登録します。

$ mkdir -p datasets/titanic
$ cd datasets/titanic
$ kaggle competitions download -c titanic
$ unzip titanic.zip
$ rm titanic.zip
$ ls
gender_submission.csv   test.csv                train.csv

この時点では、追加したファイルは未追跡のファイルとして認識されています。

次に、DVCで管理するように設定します。

$ dvc add datasets/titanic
100% Adding...|█████████████████████████████████████████████████|1/1 [00:00, 43.52file/s]
                                                                                                                                                                                  
To track the changes with git, run:

        git add datasets/titanic.dvc datasets/.gitignore

To enable auto staging, run:

        dvc config core.autostage true

新たにdatasets/titanic.dvcdatasets/.gitignoreが作成されました。

datasets/titanic.dvctitanicディレクトリのMD5ハッシュ等の情報を保持しており、

outs:
- md5: bf1a6a19059092be578a3807608e236c.dir
  size: 93081
  nfiles: 3
  path: titanic

datasets/.gitignoreはDVCで管理するように指定したtitanicディレクトリが設定されています。

/titanic

ここまでの変更をコミットしておきましょう。

リモートストレージに保存する

今の状態は追加したデータセットをGitリポジトリの管理下から除外し、管理情報だけをGitリポジトリで管理するようにしただけです。実際のデータセットはローカルにしか存在しません。

これをさきほど設定したS3バケットに保存しましょう。

dvc pushコマンドで保存できますが、これまでの手順通りに進めた場合、以下のようにエラーが発生します。

$ dvc push
ERROR: unexpected error - s3 is supported, but requires 'dvc-s3' to be installed: No module named 'dvc_s3'

Having any troubles? Hit us up at https://dvc.org/support, we are always happy to help!

DVCではS3をサポートしていますが、追加のモジュールが必要となるようです。では、モジュールを追加します。

$ pip install dvc-s3
または
$ conda install -c conda-forge dvc-s3

DVCをインストールしたときと同じ方法でインストールしてください。インストールができたら、再度dvc pushコマンドを実行します。

$ dvc push
4 files pushed

コンソールに出力された内容をみると、4ファイル保存したようですが、datasets/titanicディレクトリには3ファイルしかないはずです。リモートストレージに保存されている内容を確認してみましょう。

$ aws s3 ls s3://datascience-dvc-remote-storage
                           PRE 02/
                           PRE 61/
                           PRE b5/
                           PRE bf/
$ aws s3 ls s3://datascience-dvc-remote-storage/02/
2023-01-07 22:25:47      28629 9c9cd22461f6dbe8d9ab01def965c6
$ aws s3 ls s3://datascience-dvc-remote-storage/61/
2023-01-07 22:25:47      61194 fdd54abdbf6a85b778e937122e1194
$ aws s3 ls s3://datascience-dvc-remote-storage/b5/
2023-01-07 22:25:47       3258 6943b6ee3d9af0913ee5dd83b3d729
$ aws s3 ls s3://datascience-dvc-remote-storage/bf/
2023-01-07 22:25:47        218 1a6a19059092be578a3807608e236c.dir

最後のファイルだけ.dirとなっており、上3ファイルが各CSVファイルで、一番最後がtitanicディレクトリになります。

リモートストレージからデータセットを取得する

前述のとおり、データセット自体はGitリポジトリで管理されていません。そのため、新たにリポジトリをcloneした場合、データセットが存在状態となります。ですので、リモートストレージからデータセットをベット取得してくる必要があります。

ここでは、titanicディレクトリを削除してからデータセットを取得してみます。

$ rm -rf datasets/titanic
$ dvc pull
A       datasets/titanic/                                                                                                                                                         
1 file added
$ ls datasets/titanic
gender_submission.csv   test.csv                train.csv

データセットがdvc pullコマンドを実行することで取得できました。

また、引数でdvcファイルを指定することで、明示的に特定のファイル/ディレクトリだけを取得することができます。

$ dvc pull datasets/titanic.dvc

必要なデータセットだけ取得できるため、実務ではこちらの方がよく使うことになると思います。ただし、DVCの管理下に追加する単位が取得できる最小単位となるため、データセット単位で管理下に加えるのか、ファイル単位で管理下に加えるのかはプロジェクトによって検討する必要があります。

最後に

DVCでは、単にデータセットを管理するツールではなく、他にも機能があります。本記事では、その中のデータセットの管理について説明しました。

TypeScriptでJestを使ったテスト環境を構築する

TypeScriptでJestを使ったテスト環境を構築します。

パッケージのインストール

必要なパッケージをインストールします。

$ npm install -D jest ts-jest @types/jest ts-node

ts-nodeはTypeScriptの環境構築の過程ですでインストールしている場合があります。インストールしていない場合はts-nodeもインストールしてください。

設定ファイルを作成する

設定ファイルを作成します。本手順でインストールしたバージョンは29.3.1ですが、バージョンによって挙動や質問の内容が変更になっている場合があるのでご注意ください。

$ npx jest --init

The following questions will help Jest to create a suitable configuration for your project

✔ Would you like to use Jest when running "test" script in "package.json"? … yes
✔ Would you like to use Typescript for the configuration file? … yes
✔ Choose the test environment that will be used for testing › node
✔ Do you want Jest to add coverage reports? … yes
✔ Which provider should be used to instrument code for coverage? › v8
✔ Automatically clear mock calls, instances, contexts and results before every test? … yes

✏️  Modified /Users/t0k0sh1/Workspace/honeycomb/packages/cli/package.json

📝  Configuration file created at /Users/t0k0sh1/Workspace/honeycomb/packages/cli/jest.config.ts

ここでは、TypeScriptで設定ファイルを書く設定(2つ目の質問)にしています。ただ、実際に設定ファイルを出力してみると、JavaScriptで書かれた設定ファイルjest.config.jsも出力されました。これが正しい挙動かは不明ですが、複数の設定ファイルがあるとjestコマンドが実行できないため、以下のいずれかの対応を行なってください。

  • TypeScriptで設定ファイルを定義したい場合はjest.config.jsjest.config.js.mapを削除する
  • JavaScriptで設定ファイルを定義したい場合は2つ目の質問でnoを選択する

設定ファイルの出力後、jest.config.tsに1箇所修正を加えます。

export default {
  // A map from regular expressions to paths to transformers
- // transform: undefined,
+ transform: {
+   "^.+\\.(ts|tsx)$": "ts-jest",
+ },
}

この設定はテストコードを書いた時にimport/exportが使用できるようにするための設定です。

テストコードを書く

実際にテストコードを書いてみましょう。

まずはテスト対象のコードです。

export function greet(name: string): string {
  return `Hello ${name}`;
}

次にテストコードです。前述で設定を行なっているため、テストコード内でimportが使用可能です。

import { greet } from "./greeting";

test("Greeting is", () => {
  expect(greet("John")).toBe("Hello John");
});

テストを実行すると以下のようになります。

$ npm run test

> example@.1.0 test
> jest

 PASS  src/greeting.spec.ts
 PASS  dist/greeting.spec.js
-------------|---------|----------|---------|---------|-------------------
File         | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-------------|---------|----------|---------|---------|-------------------
All files    |     100 |      100 |     100 |     100 |                   
 greeting.ts |     100 |      100 |     100 |     100 |                   
-------------|---------|----------|---------|---------|-------------------

Test Suites: 2 passed, 2 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        0.866 s, estimated 1 s
Ran all test suites.

Node.jsでTypeScriptの環境を構築する

Node.jsでTypeScriptの環境を構築します。

構築する環境について

本記事では、以下のバージョンで構築しています。

$ node -v
v18.12.1
$ npm -v
9.1.2

以降の手順で、 Node.jsのバージョンが必要となりますので、必ず確認してください。

TypeScriptをインストールする

TypeScriptをインストールしていきます。

$ npm install -D typescript @types/node@18

使用しているバージョンがv18.12.1ですので、@typesパッケージも同じバージョンのものを指定します。

インストールできたらインストールされているバージョンを確認します。

$ npx tsc --version
Version 4.9.4

上記のようにtscコマンドを使ってバージョンが表示できればインストールは完了しています。

tsconfig.jsonを作成する

次にTypeScriptの設定ファイルのtsconfig.jsonを作成します。まずは、以下のコマンドを実行してファイルを作成します。

$ npx tsc --init

このままでも動作しますが、一部設定を変更しておきます。

{
  "compilerOptions": {
-   // "outDir": "./",               /* Specify an output folder for all emitted files. */
+   "outDir": "./dist",              /* Specify an output folder for all emitted files. */
- }
+ },
+ "include": [
+   "src/**/*"
+ ]
}

ここでは、TypeScriptファイルの格納先(include)とコンパイルして作成されるJavaScriptファイルの出力先(outDir)を追加・変更しています。

環境の構築時期やTypeScriptのバージョン、プロジェクトの都合によっては他の設定も変更することがありますが、ここでは省略します。

動作確認

実際に動作確認をしてみましょう。まずはsrc/index.tsを作成し、ファイルの中身は以下のようにします。

function greet(name: string): string {
  return `Hello, ${name}!`;
}

console.log(greet("John"));

以下のコマンドを実行し、src/index.tsをコンパイルします。

$ npx tsc

ファイルはdist/index.jsにされ、設定の違いで多少異なるかもしれませんが、以下のように出力されます。

"use strict";
function greet(name) {
    return `Hello, ${name}!`;
}
console.log(greet("John"));

実行にはJavaScriptファイルを使用します。

$ node dist/index.js
Hello, John!

エラーなくメッセージが表示されれば正しくコンパイルされています。

package.jsonにスクリプトを追加する

package.jsonにスクリプトを追加してnpmコマンドでビルドできるようにします。

{
  "scripts": {
-   "test": "echo \"Error: no test specified\" && exit 1"
+   "build": "tsc",
+   "watch": "tsc --watch"
  },
}

ここでは2つのスクリプトを追加しています。ひとつはビルドを行うスクリプト(build)で、もう一つは変更を監視して変更があればビルドを行うスクリプトです(watch)。

追加したコマンドは以下のように実行します。

$ npm run build
$ npm run watch

M1/M2 Macで機械学習の環境を構築する

TensorflowとPytorchがApple Siliconに対応したため、Pythonの機械学習・ディープラーニング環境を構築します。

仮想環境の作成

仮想環境を作成します。

使用するPythonのバージョンですが、このあとインストールするTensorflowが執筆時点では3.7から3.10をサポートしており、Pytorchが3.7以上をサポートしているため、3.10を使用することにします。

conda create -n datascience python=3.10
conda activate datascience

ここでは仮想環境の名前をdatascienceにしていますが、任意の名前で構いません。

機械学習関連

機械学習関連のパッケージをインストールします。

機械学習でよく使われるパッケージをインストールします。

conda install numpy scipy pandas scikit-learn

代表的な可視化パッケージをインストールします。

conda install matplotlib seaborn plotly

EDAパッケージをインストールします。

conda install -c conda-forge pandas-profiling autoviz sweetviz

ローコード機械学習をインストールします。

conda install -c conda-forge pycaret

Jupyter notebookをインストールします。

conda install notebook

スクレイピング関連

スクレイピングでよく使用されるパッケージをインストールします。

conda install -c conda-forge requests scrapy beautifulsoup4

画像処理関連

画像処理でよく使用されるパッケージをインストールします。

conda install -c conda-forge pillow opencv

ディープラーニング関連

TensorflowとPytorchをインストールします。

Tensorflow

Xcode Command Line Toolをインストールしていない場合は以下のコマンドでインストールします。 

xcode-select --install

Tensorflow dependenciesをインストールします。

conda install -c apple tensorflow-deps

Tensorflowをインストールします。

pip install tensorflow-macos

Metalプラグインをインストールします。

pip install tensorflow-metal

インストール後にGPUが使用可能か確認しましょう。

import sys
import tensorflow.keras
import pandas as pd
import sklearn as sk
import scipy as sp
import tensorflow as tf
import platform

gpu = len(tf.config.list_physical_devices('GPU'))>0
print("GPU is", "available" if gpu else "not available")

以下のように表示されればGPUが使用可能です。

GPU is available

Pytorch

PytorchはTensorflowに比べるとインストールは簡単です。以下のコマンドでインストールします。

pip install --pre torch torchvision --extra-index-url https://download.pytorch.org/whl/nightly/cpu

インストール後にGPUが使用可能か確認しましょう。

import torch

gpu = torch.backends.mps.is_available()
print("GPU is", "available" if gpu else "not available")

以下のように表示されればGPUが使用可能です。

GPU is available

今後の課題

現時点で形態素解析パッケージであるMecabのインストールに失敗しています。手順もいくつか示されていますが、実際に試したところいずれもうまくいっていません(インストール自体に失敗する、インストール後に動作しない)。

こちらは引き続きインストール方法を調査し、判明次第本記事を更新したいと思います。

[Ansible]SSHがUNREACHABLEになるときの対処方法

Ansibleを使っていて、SSH接続がUNREACHABLEになる場合の対処方法について説明します。

事象について

ここで説明する事象は以下のようなものです。

$ ansible all -m ping
server1 | UNREACHABLE! => {
    "changed": false,
    "msg": "Failed to connect to the host via ssh: Warning: Permanently added 'server1,192.168.1.1' (ECDSA) to the list of known hosts.\r\nansible@server1: Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password).",
    "unreachable": true
}

疎通確認のためにpingを実行してみると、対象サーバーに到達できない(UNREACHABLE)というエラーが返ってきます。

ちなみに、sshコマンドを使って接続してみると、エラーなく接続できますし、

$ ssh ansible@server1
ansible@server1's password: 
[ansible@server1 ~]$

pingコマンドも通ります。

$ ping server1
PING server1 (192.168.1.1) 56(84) bytes of data.
64 bytes from server1 (192.168.1.1): icmp_seq=1 ttl=64 time=0.141 ms
64 bytes from server1 (192.168.1.1): icmp_seq=2 ttl=64 time=0.617 ms
64 bytes from server1 (192.168.1.1): icmp_seq=3 ttl=64 time=0.429 ms
^C
--- server1 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2039ms
rtt min/avg/max/mdev = 0.141/0.395/0.617/0.195 ms

原因と対処方法

Ansibleでは、pingを実行する前にSSH接続しているのですが、このとき特にオプション指定をしなければ、公開鍵認証になります。

前述でSSH接続にはパスワード認証を行っていたので、これが接続できない原因となります。対処方法は単純で、パスワード認証でSSH接続するようにします。

具体的な手順

まずは、sshpassパッケージをインストールします。Ubuntuの場合、以下のようにしてパッケージをインストールしてください。

$ apt-get install sshpass
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following NEW packages will be installed:
  sshpass
0 upgraded, 1 newly installed, 0 to remove and 122 not upgraded.
Need to get 10.3 kB of archives.
After this operation, 29.7 kB of additional disk space will be used.
Get:1 http://ports.ubuntu.com/ubuntu-ports focal/universe arm64 sshpass arm64 1.06-1 [10.3 kB]
Fetched 10.3 kB in 1s (12.5 kB/s) 
debconf: delaying package configuration, since apt-utils is not installed
Selecting previously unselected package sshpass.
(Reading database ... 25842 files and directories currently installed.)
Preparing to unpack .../sshpass_1.06-1_arm64.deb ...
Unpacking sshpass (1.06-1) ...
Setting up sshpass (1.06-1) ...

もし、以下のようなエラーが発生する場合は、先にapt-get updateを実行してください。

Reading package lists... Done
Building dependency tree       
Reading state information... Done
E: Unable to locate package sshpass

sshpassがインストールできたら、再度コマンドを実行しますが、実行の際に--ask-passオプションを指定します。

$ ansible --ask-pass all -m ping
SSH password: 
server1 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": false,
    "ping": "pong"
}

pingが成功したことを確認できました。

毎回オプションを指定するのが面倒な場合は、ansible.cfgask_pass = Trueを書いておくことで省略できます。

[defaults]
ask_pass = True

[Node.js][npm]ローカルパッケージを更新する

ローカルパッケージを更新する手順について説明します。

本記事では、複数のパッケージを一気にバージョンアップする方法については解説しません。ライブラリやフレームワークによっては公式でバージョンアップデート方法やマイグレーション方法を説明している場合があります。そのような場合は本手順ではなく、公式の手順に従うようにしてください。

また、パッケージのバージョンアップは十分注意して行うようにしてください。バグフィックスであっても意図しない動作をする可能性がありますので、十分テストした上でバージョンアップすることが大切です。

手順

sassパッケージをアップデートする例で手順を説明します。

{
  ...
  "devDependencies": {
    "sass": "^1.56.1"
  }
}

執筆時点では、sassパッケージの最新バージョンは1.56.2ですので、1.56.1から1.56.2へのバージョンアップを試みます。

アップデートの有無を確認する

エディタの機能等で最新バージョンを確認できる方は必要ありませんが、コマンドで最新バージョンが存在するかを確認することができます。

$ npm outdated
Package  Current  Wanted  Latest  Location           Depended by
sass      1.56.1  1.56.2  1.56.2  node_modules/sass  npm-update-sample

前述のとおり、現在バージョン(Current)は1.56.1で最新バージョン(Latest)は1.56.2であることがわかります。

各項目の意味は以下のとおりです。

  • Package:最新バージョンがあるパッケージ(現在のバージョンが最新バージョンの場合は表示されない)
  • Current:現在インストールされているバージョン
  • Wanted:package.jsonに記載されたセマンティックバージョンの条件を満たす最新バージョン
  • Latest:最新バージョン
  • Location:インストール先
  • Depended by:このパッケージに依存しているパッケージ

パッケージをアップデートする

アップデートを確認できましたので、実際にアップデートを行っていきます。

ここでは、すべてのパッケージをアップデートするのではなく、バージョンアップしたいsassパッケージだけをアップデートし、1.56.2へ狙い撃ちでバージョンアップする方法を説明します。

パッケージのアップデートはnpm updateコマンドで行いますが、このコマンドでは対象パッケージを指定することまではできますが、特定のバージョンを指定してアップデートすることはできません。最新バージョンではなく、特定のバージョンを指定してアップデートしたい場合はnpm installコマンドを用います。

$ npm install sass@1.56.2

changed 1 package, and audited 39 packages in 669ms

4 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities

sassパッケージはdevDependenciesにありますが、バージョンアップするときはオプションなしでアップデートできます。

{
  ...
  "devDependencies": {
    "sass": "^1.56.2"
  }
}

package.jsonを確認するとバージョンアップしていることが確認できます。

Visual Studio Codeでキーボードショートカットが効かなくなった時に確認すること

Visual Studio Codeでいつも使えていたキーボードショートカットが使えなくなったり、新たにキーボードショートカットを使おうとして期待していた動きと違う場合に、どこを確認して、どう対処すればいいかを解説します。

どういったことが起きている可能性が高いのか

まず、キーボードショートカットが効かなかったり、期待した動きをしていない場合、どういったことが起きているかについて説明します。

このような事象が起きている原因には、大きく3つの可能性が考えられます。

  • コマンドに割り当てられていたキーボードショートカットが削除されている
  • キーボードショートカットが別のコマンドに割り当てられている
  • キーボードショートカットが他のキーボードショートカットの一部となっている

次に私が遭遇した具体的な事例をもとに手順を確認していきます。

キーボードショートカットの設定を確認する

まずはキーボードショートカットの設定を確認しましょう。

キーボードショートカットの設定を表示するには、Ctrl+K Ctrl+S(macOSはCommand+K Command+S)を入力します。

キーボードショートカットを確認する

やり方はいくつかありますが、まずはキーボードショートカットが設定されているのかを確認します。

上部にあるテキストボックスの右側にあるキーボードのマークをクリックすると、キーボードショートカットで検索することができるようになります。

テキストボックスでキーボードショートカットを入力すると、対象のキーボードショートカットが割り当てられているコマンドに絞り込まれます。

ここでは、行全体を選択するキーボードショートカットのCtrl+L(macOSではCommand+L)が効かなかったので、調べています。

見たところ、キーボードショートカットは自体は正しく設定されているようです。

キーボードショートカットを修正する

調べた結果を元に、具体的に修正を行なっていきます。

コマンドが見つからなかった場合

キーボードショートカットを入力しても期待していたコマンドがヒットしなかったときは、何らかの理由でキーボードショートカットが解除されたか、別のコマンドに割り当てられています。

その場合は、再度 キーボードショートカットを割り当ててください。

コマンドが見つかった場合

コマンドが見つかった場合、当該キーボードショートカットを一部に持つ別のコマンドが割り当てられてる可能性が高いです。

これを確認するために、キーボードショートカットを再度して、ステータスバーを確認してみてください。他のキーボードショートカットの一部になっている場合は以下のように2番目のキーを待つ表示が現れます。

該当のコマンドが何かもわかりませんし、2番目のキーがわからないとキーボードショートカットでも探せないため、地道ですが目視で探してください。

本例では拡張機能「Live Server」のキーボードショートカットの一部にCtrl+L(macOSの場合はCommand+L)が使われており、これによって本来実行したかった行全体を選択が使用できなくなっていました。

問題を解決するには他のショートカットキーに変更するかキーボードショートカットを削除してください。

対象のキーボードショートカットを右クリックし、変更したい場合は「キー バインドを変更する…」を選択、削除したい場合は「キー バインドを削除」を選択します。
今回は特に使っていないキーボードショートカットだったので、削除することにしました。

動作確認をする

修正が完了したら動作確認をしてみましょう。

問題なくキーボードショートカットが機能していれば問題解決です。

[macOS] iTerm2で自動的にログを取得する設定を行う

セッション開始時に自動的にログを取得する方法について解説します。

ログの出力先を用意する

作成先はどこでも構いません。使用量にもよりますが、長期間運用しているとそれなりのサイズとなるため、空き容量が少ないストレージや容量が圧迫したときに動作に影響のあるストレージは避けた方がよいでしょう。

特に、容量の少ないMacBookを使用している場合は、すぐにディスクがいっぱいになる場合がありますので、外部の大容量ストレージを使うか、ログを定期的に削除するなどの対策をご検討ください。

本記事では、Google Drive for desktopで作成されるGoogle Driveにログを出力するディレクトリを作成しています。

iTerm2のプロファイル(Profile)を開く

iTerm2のメニューからProfiles > Open Profiles...Command+O)でProfilesダイアログを開きます。

Profilesダイアログ

利用状況にもよりますが、星マークがついているProfile Nameが現在使用しているプロファイル(設定)になります。多くの型はDefaultに星マークがついていると思いますが、私の環境ではGuakeを使用しているため、Guakeプロファイルに星マークがついています。

星マークがついている行を選択し、Edit Profiles...を選択してください。

Preferencesダイアログ

ProfilesタブのSessionタブに移動し、Miscellaneousの「Automatically log session input to files in:」にチェックをつけ、ログの保存先のディレクトリのパスをテキストボックスに入力します。

セッション開始時にログを自動的に作成する設定

変更は保存操作をしなくても即時反映されるため、作業はこれで完了ですので、そのまま閉じてください。

ログが出力されることを確認する

では、実際にセッションを新規作成してログファイルが作成されることを確認してみましょう。

iTerm2のメニューからShell > New WindowCommand+N)もしくはShell > New TabCommand+T)で新しいセッションを開始します。
セッション開始後、Finderでログの出力先にファイルが作成されたことを確認します。

特にファイル名は指定していませんが、ファイル名にセッションを開始した年月日時分秒が含まれていますので、後で探すときに困ることはなさそうです。

では、ファイルを開いてみましょう。ここではテキストエディット.appでファイルを開いています。

ログファイル

Shellの設定によりますが、私の環境ではzshellを使用し、Powerlevel10Kを導入しているため、非常に見にくくなっています。この時点で読める表示になっている方は以降の手順は必須ではありませんが、そうでない方は以降で説明する設定を行ってみてください。

ログをプレーンテキストで出力する

先ほどの設定に戻り、「Log plain text」にチェックをつけます。

Preferencesダイアログ

これで、再度セッションを開始してログを出力した後で、ログファイルをテキストエディット.appで開いてみます。

ログファイル

多少文字化けしている箇所はありますが、先ほどに比べると圧倒的に読みやすくなっています。

「Log plain text」チェックボックスのON、OFFを両方試していただいて環境にあった方を選択してください。

Pandasで日付項目を日付型として扱う

Pandasで日付項目をdatetime[ns]型に変換し、日付型として扱う方法について解説します。

日付項目を読み込む

次のCSVファイルを特にオプションを指定せずに読み込みます。

date1        ,date2      ,date3     ,date4   ,date5     ,date6   ,date7
2020年12月31日,2020年6月9日,2020-12-31,2020-6-9,2020/12/31,2020/6/9,20201231

このファイルには4種類(うち3種類は0埋めありとなしの2パターン用意)の日付項目が設定されています。

import pandas as pd
df = pd.read_csv('test.csv')

各項目がどの型で読み込まれているかinfo関数で確認します。

df.info()

yyyymmdd形式はint64型、それ以外はobject型(str型)で読み込まれているのがわかります。

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1 entries, 0 to 0
Data columns (total 7 columns):
 #   Column  Non-Null Count  Dtype 
---  ------  --------------  ----- 
 0   date1   1 non-null      object
 1   date2   1 non-null      object
 2   date3   1 non-null      object
 3   date4   1 non-null      object
 4   date5   1 non-null      object
 5   date6   1 non-null      object
 6   date7   1 non-null      int64 
dtypes: int64(1), object(6)
memory usage: 184.0+ bytes

日付型に変換する

日付項目を加工したり、年・月・日などを取り出しやすくするために、datetime64[ns]型に変換しておくと便利です。

datetime64[ns]型に変換するには、pandas.to_datetime関数を使います。

df['datetime1'] = pd.to_datetime(df['date1'], format="%Y年%m月%d日")
df['datetime2'] = pd.to_datetime(df['date2'], format="%Y年%m月%d日")
df['datetime3'] = pd.to_datetime(df['date3'])
df['datetime4'] = pd.to_datetime(df['date4'])
df['datetime5'] = pd.to_datetime(df['date5'])
df['datetime6'] = pd.to_datetime(df['date6'])
df['datetime7'] = pd.to_datetime(df['date7'], format="%Y%m%d")

年月日形式の項目はformatオプションを指定しないとエラーになります。また、yyyymmdd形式はエラーにはなりませんが、値をナノ秒と見なして読み込むため、1970-01-01 00:00:00.020201231のような値になってしまいます。こちらもformatオプションの指定が必要です。

読み込み時に 日付型に変換する

読み込んでみてから、「あ、これ日付項目か」と気づく場合は前述の方法を使っていただければよいですが、事前にどれが日付項目かわかっている時は読み込む時に日付型として読み込む方が効率的です。

標準の日付パーサーで変換できる場合

yyyy-mm-dd形式やyyyy/mm/dd形式、yyyymmdd形式の場合は標準の日付パーサーで変換できます。

次のような形式の CSVファイルの場合、

date    ,average
2021/8/1,28.7
2021/8/2,28.6
2021/8/3,29.0
2021/8/4,29.5
2021/8/5,29.1
2021/8/6,29.1
2021/8/7,27.9

以下のようにすることで、項目dateを日付datetime64[ns]型で読み込むことができます。

df = pd.read_csv('weather.csv', 
                 dtype={"date": str},
                 parse_dates=["date"])
df.info()

直接dtypedatetime64を指定するのではなく、一旦dtypeオプションではstr型を指定して、parse_datesオプションで日付型にしたい項目を指定して変換するというやり方になります。

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 7 entries, 0 to 6
Data columns (total 2 columns):
 #   Column    Non-Null Count  Dtype         
---  ------    --------------  -----         
 0   date      7 non-null      datetime64[ns]
 1    average  7 non-null      float64       
dtypes: datetime64[ns](1), float64(1)
memory usage: 240.0 bytes

日付パーサーを自作して変換する場合

年月日形式などPandasが用意している標準の日付パーサーで変換できない場合は日付パーサーを自作して指定することで日付変換ができるようになります。

次のようなCSVファイルの場合、

date,       average
2021年8月1日,28.7
2021年8月2日,28.6
2021年8月3日,29.0
2021年8月4日,29.5
2021年8月5日,29.1
2021年8月6日,29.1
2021年8月7日,27.9

先ほどと同じコードで読み込むと、エラーは発生しませんが、datetime64[ns]型には変換されません。

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 7 entries, 0 to 6
Data columns (total 2 columns):
 #   Column    Non-Null Count  Dtype  
---  ------    --------------  -----  
 0   date      7 non-null      object 
 1    average  7 non-null      float64
dtypes: float64(1), object(1)
memory usage: 240.0+ bytes

このような場合は、日付パーサーを自作し、date_parserオプションで指定します。

from datetime import datetime
my_parser = lambda date: datetime.strptime(date, '%Y年%m月%d日')
df = pd.read_csv('weather.csv', 
                 dtype={"date": str},
                 parse_dates=["date"],
                 date_parser=my_parser)
df.info()

先ほどとは異なり、datetime64[ns]型に変換されていることが確認できます。

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 7 entries, 0 to 6
Data columns (total 2 columns):
 #   Column    Non-Null Count  Dtype         
---  ------    --------------  -----         
 0   date      7 non-null      datetime64[ns]
 1    average  7 non-null      float64       
dtypes: datetime64[ns](1), float64(1)
memory usage: 240.0 bytes

pandas.datetime.strptimeを使用するサンプルを見かけると思いますが、pandas.datetimeは将来的に削除される予定ですので、今後はdatetimeを使用しましょう。
/var/folders/3r/qfsmvnsd5sz0qvf367p_d5j00000gp/T/ipykernel_83309/1860031930.py:1: FutureWarning: The pandas.datetime class is deprecated and will be removed from pandas in a future version. Import from datetime module instead.
my_parser = lambda date: pd.datetime.strptime(date, ‘%Y年%m月%d日’)

質的変数と量的変数

統計学で扱うデータ(変数)は、質的変数と量的変数に分類できます。

質的変数(qualitative variable)

質的変数とは、データをいくつかに分類したもの(それぞれをカテゴリといいます)の中から1つのカテゴリを取るような変数です。質的変数の具体例には、性別(男、女)、血液型(A型、B型、AB型、O型)、学校の成績(A、B、C、D、E、F)、病気の進行段階(ステージ0、ステージⅠ、ステージⅡ、ステージⅢ、ステージⅣ)などがあります。
質的変数は、名義尺度と順序尺度に分けることができます。

名義尺度(nominal scale)

質的変数のうち、カテゴリ間に順序性がないものを名義尺度といいます。名義尺度の具体例には性別、血液型などがあります。

順序尺度(ordinal scale)

質的変数のうち、カテゴリ間に順序性があるものを順序尺度といいます。名義尺度に加え、順序にも意味がある尺度ともいうことができます。順序尺度の具体例には学校の成績や病気の進行段階などがあります。

量的変数(quantitative variable)

量的変数とは、数値で与えられる変数です。量的変数の具体例には、摂氏温度、身長、体重、世帯人数、西暦などがあります。

間隔尺度(interval scale)

量的変数のうち、各値の間隔に意味があるものを間隔尺度といいます。順序尺度に加え、値の間隔にも意味がある尺度ともいうことができます。間隔尺度の具体例には摂氏温度、世帯人数、西暦などがあります。

比例尺度(ratio scale)

量的変数のうち、ある値が他の値と比較して何倍あるかに意味があるものを比較尺度といいます。間隔尺度に加えて、比にも意味がある尺度ということができます。比例尺度の具体例には身長や体重などがあります。

どちらに分類されるかは変わることがある

ある変数が質的変数か量的変数かということについては、ある程度の傾向はあるものの、絶対にこちらだということはありません。

例えば、日付はある日を表すラベルと見なせば質的変数(順序尺度)として扱うこともできますが、日付の差に着目する場合は量的変数(間隔尺度)として扱うこともあります。テストの点数でも、0点から100点までの量的変数(比例尺度)として捉えることもできますが、0点〜10点、11点〜20点・・・のように度数で扱うなら質的変数(順序尺度)として捉えることもできます。

このように、どのように収集するのか、どう集計するのか、どのように扱うのか、どこに注目するのか、などによって同じ変数であっても分類が変わることがあることに注意が必要です。過去に質的変数で扱っていたとしても、今回はどのように扱うかきちんと精査することが大切です。

kubectlコマンドでリモートクラスタに接続する

リモートサーバーに構築したkubernatesにローカルからアクセスできるようにします。

認証情報を出力する

本例ではmicrok8sでKubernetesクラスターを構築しています。

まずは、リモートサーバーにSSH等で接続し、認証情報を取得します。

$ microk8s kubectl config view --raw

上記コマンドで出力すると、以下のような内容が出力されます(一部、内容を変更しています)。

apiVersion: v1
clusters:
- cluster:
    certificate-authority-data:xxxxxx
    server: https://127.0.0.1:16443
  name: microk8s-cluster
contexts:
- context:
    cluster: microk8s-cluster
    user: admin
  name: microk8s
current-context: microk8s
kind: Config
apiVersion: v1
clusters:
- cluster:
    server: https://192.168.0.16:16443
  name: microk8s-cluster
contexts:
- context:
    cluster: microk8s-cluster
    user: admin
  name: microk8s
current-context: microk8s
kind: Config
preferences: {}
users:
- name: admin
  user:
    password: xxxxx
    username: admin
apiVersion: v1
apiVersion: v1
apiVersion: v1
preferences: {}
users:
- name: admin
  user:
    token: xxxxx

ローカルに認証情報を設定する

前述の出力内容のうち、以下の部分が127.0.0.1になっているため、IPアドレスをリモートアドレスに書き換えます。

- cluster:
    certificate-authority-data:xxxxxx
    server: https://127.0.0.1:16443
  name: microk8s-cluster

server欄をリモートアドレスに書き換えます。

- cluster:
    certificate-authority-data:xxxxxx
    server: https://192.168.0.16:16443
  name: microk8s-cluster

これを~/.kube/configに設定します。

ファイル自体がない場合はそのまま設定してもらってよいのですが、すでに設定がある場合は必要な部分だけを追記してください。

モバイルバージョンを終了