📘

VSCode + DockerでAtCoderのテスト・提出ができる環境構築【Python,PyPy】

2023/01/02に公開約5,500字2件のコメント

はじめに

私は2022年9月からAtCoderを始めて、今までサイト内にあるコードテストを使ってPython・PyPy3で問題を解いていました。
しかし、サンプルのテスト・提出をするのに毎度コピー&ペーストするのが煩わしくコマンド一つで完結させたいのと、ローカル環境下に色々インストールすると今後依存関係等で大変になるかと思い、VSCode + Dockerを使って簡単にテスト・提出ができる環境構築を行いました。
環境はWindows10を使用しています。

準備

以下のものがインストールされていない場合は事前に準備をしておきます。
細かいインストール手順等は今回のメインではないため割愛させていただきます。

VSCode

今回はエディターにVSCodeを使用するのでインストールをします。
VSCodeからDockerのコンテナ内に入って作業行うので、拡張機能「Remote-Containers」をインストールします。

Docker

私はWindows10環境なのでDocker Desktop for Windowをインストールしました。

git

リポジトリをクローンしますので、gitをインストールします。

環境構築

  1. コマンドプロンプトの任意のディレクトリにて次のコマンドを実行。
     $git clone https://github.com/gomatofu/atcoder_python.git
     $code atcoder_python
    
  2. VSCodeでRemote-Containers: Reopen in Containerを選択。

すると以下のディレクトリ構成となります。

atcoder_python/
     └ .devcontainer/
             ├ Dockerfile
             ├ devcontainer.json
             ├ docker-compose.yml
             └ requirements.txt
     └ contest/

  • .devcontainer
    • .devcontainer内ではPython、PyPy、online-judge-tools、atcoder-cli等のインストールの設定を記述しています。
  • contest
    • contest内では実際にAtCoderの問題を解いたり、テストしたりする場所として用意しています。

設定

ここからはVSCodeのターミナルで操作となります。

  1. ディレクトリ:/atcoder_pythonにて次のコマンドを実行。atcoder-cli使用のためAtCoderログイン作業。

     $acc login
    
  2. AtCoderのusername、passwordが聞かれるため、入力し実行。初回のみ必要となる。

  3. ディレクトリ:/atcoder_pythonにて次のコマンドを実行。online-judge-tools使用のためAtCoderログイン作業。

     $oj login https://beta.atcoder.jp/
    
  4. 再びAtCoderのusername、passwordが聞かれるため、入力し実行。初回のみ必要となる。警告が出るが問題ない。

  5. ディレクトリ:/atcoder_pythonにて次のコマンドを実行。問題インストール時にデフォルトは1問ずつしかインストールされないが全問インストールされるように変更。

     $acc config default-task-choice all
    
  6. テンプレートファイルの設定をPythonに変更するためatcoder-cliの設定フォルダへ移動。

     $cd `acc config-dir`
    
  7. Pythonディレクトリを作成し、main.pyとtemplate.jsonの作成を行う。

     $mkdir python
     $cd python
     $touch template.json
     $touch main.py
     $code template.json
    
  8. template.jsonの設定を行う。

    template.json
     {
     "task":{
       "program": ["main.py"],
       "submit": "main.py"
         }
     }
    
  9. デフォルトのテンプレートをpythonに変更。

     $acc config default-template python
    

ここまででPython、PyPyで問題を解くための設定は終わりました。


ここからはテスト・提出のコマンドが長いので、コマンドを簡単にするためエイリアス設定を行っていきます。
あくまで私がわかりやすいようにコマンド名を決めているのでお好みで変更してください。

  1. .bashrcを作成します。

     $cd ~
     $touch .bashrc
     $code .bashrc
    
  2. .bashrcにエイリアス設定をしていきます。

    .bashrc
     # PyPy3でのテスト実施
     alias test='oj t -c "pypy3 main.py" -d ./tests/'
     # Pythonでのテスト実施
     alias test2='oj t -c "python3 main.py" -d ./tests/'
    
     # PyPy3での解答提出
     alias sb='acc s main.py -- --guess-python-interpreter pypy'
     # Pythonでの解答提出
     alias sb2='acc s main.py'
    
     # コンテストフォルダへ移動
     alias c='cd contest'
    
     # main.pyを開く
     alias o='code main.py'
    
     # 出力確認用
     alias d='python main.py'
    

これでコマンドの設定は終わりました。

使い方

ここから実際に問題を解いていきましょう。

問題作成

contestフォルダへ移動し、acc new [ContestName]を実行すると、以下のディレクトリが作成される。
[ContestName]: は解答したいコンテストの名前を入力。(例:abc248、abc255等)

 $ acc new abc248

 contest/
     └ abc248
         ├── a
         │   ├── main.py
         │   └── tests
         │       ├── sample-1.in
         │       ├── sample-1.out
         ...
         │       ├── sample-3.in
         │       └── sample-3.out
         ├── b
         │   ├── main.py
         │   └── tests
         │       ├── sample-1.in
         │       ├── sample-1.out
         ...
         │       ├── sample-3.in
         │       └── sample-3.out
         ├── c
         │   ├── main.py
         │   └── tests
         │       ├── sample-1.in
         │       ├── sample-1.out
         ...
         │       ├── sample-3.in
         │       └── sample-3.out
         ...
         └─ contest.acc.json

解答

解答したい問題のディレクトリに移動し、main.pyを開き解答を行っていきます。

 $cd abc248	   # 解答したいコンテスト
 $cd a		   # 解答したい問題
 $o		       # main.pyを開く

テスト

問題が解き終わったらサンプルのテストケースをもとにテストを行っていきます。

 $test	       # PyPy3でテストしたい場合
 $test2	       # Pythonでテストしたい場合

ターミナル内に結果が返ってきます。
image.png

提出

問題が解き終わり提出を行っていきます。

 $sb	       # PyPy3で提出する場合
 $sb2	       # Pythonで提出する場合

提出の最終確認としてコマンドの入力を求められるので入力します。
今回は"abca"と書かれているので同じものを入力します。
image.png

すると提出が成功となります。
image.png

AtCoderのサイト内でも確認してみると、ちゃんと提出できています。
image.png

最後に

Dockerの設定等を一から行ったのは初めてなので間違っている点もあるかもしれませんが、実際に手を動かしながら行っていくと頭の中でぼんやりしていたものがはっきりとして理解が進んだかと思います。
間違っている点を見つけましたらご指摘いただけると助かります。
環境構築に満足してしまった点はありますが、本来の目的であるAtCoderの問題を解き進め、精進していきたいと思います。

Githubのレポジトリ ↓
https://github.com/gomatofu/atcoder_python

参考文献

Discussion

Docker初心者です。
参考にさせていただいております。

環境構築2.VSCodeでRemote-Containers: Reopen in Containerを選択。
にて、Starting Dev Container(show log)のlogを見ると以下の箇所で止まってしまい動きません。
解決方法、他ログなどの確認箇所など教えていただけないでしょうか。

[79 ms] Dev Containers 0.266.1 in VS Code 1.74.2 (e8a3071ea4344d9d48ef8a4df2c097372b0c5161).
[79 ms] Start: Resolving Remote
[111 ms] Setting up container for folder or workspace: c:\Users\XXX\atcoder_python
[118 ms] Start: Check Docker is running
[118 ms] Start: Run: docker version --format {{.Server.APIVersion}}
[375 ms] Server API version: 1.41
[376 ms] Start: Run: docker volume ls -q
[526 ms] Start: Run: docker volume create vscode
[734 ms] Start: Run: docker ps -q -a --filter label=vsch.local.folder=c:\Users\XXX\atcoder_python --filter label=vsch.quality=stable
[883 ms] Start: Run: docker ps -q -a --filter label=devcontainer.local_folder=c:\Users\XXX\atcoder_python
[1056 ms] Start: Run: C:\Users\XXX\AppData\Local\Programs\Microsoft VS Code\Code.exe --ms-enable-electron-run-as-node c:\Users\XXX\.vscode\extensions\ms-vscode-remote.remote-containers-0.266.1\dist\spec-node\devContainersSpecCLI.js up --user-data-folder c:\Users\XXX\AppData\Roaming\Code\User\globalStorage\ms-vscode-remote.remote-containers\data --workspace-folder c:\Users\XXX\atcoder_python --workspace-mount-consistency cached --id-label devcontainer.local_folder=c:\Users\XXX\atcoder_python --log-level debug --log-format json --config c:\Users\XXX\atcoder_python\.devcontainer\devcontainer.json --default-user-env-probe loginInteractiveShell --mount type=volume,source=vscode,target=/vscode,external=true --skip-post-create --update-remote-user-uid-default on --mount-workspace-git-root true
[1426 ms] (node:10696) [DEP0005] DeprecationWarning: Buffer() is deprecated due to security and usability issues. Please use the Buffer.alloc(), Buffer.allocUnsafe(), or Buffer.from() methods instead.
[1426 ms] (Use `Code --trace-deprecation ...` to show where the warning was created)
[1429 ms] @devcontainers/cli 0.25.2. Node.js v16.14.2. win32 10.0.19045 x64.
[1428 ms] Start: Run: docker buildx version
[2132 ms] github.com/docker/buildx v0.10.0 876462897612d36679153c3414f7689626251501
[2132 ms] 
[2133 ms] Start: Resolving Remote
[2140 ms] Start: Run: docker-compose version --short
[2480 ms] Docker Compose version: 2.15.1
[2482 ms] Start: Run: docker ps -q -a --filter label=com.docker.compose.project=atcoder_python_devcontainer --filter label=com.docker.compose.service=python
[2640 ms] Start: Run: docker-compose -f c:\Users\XXX\atcoder_python\.devcontainer\docker-compose.yml --profile * config
[2959 ms] name: devcontainer
services:
  python:
    build:
      context: c:\Users\XXX\atcoder_python\.devcontainer
      dockerfile: Dockerfile
    container_name: atcoder
    image: atcoder
    networks:
      default: null
    tty: true
    volumes:
    - type: bind
      source: c:\Users\XXX\atcoder_python
      target: /atcoder_python
      bind:
        create_host_path: true
networks:
  default:
    name: devcontainer_default
[2962 ms] Start: Run: docker events --format {{json .}} --filter event=start
[2978 ms] PersistedPath=c:\Users\XXX\AppData\Roaming\Code\User\globalStorage\ms-vscode-remote.remote-containers\data, ContainerHasLabels=false
[2979 ms] Start: Run: docker-compose -f c:\Users\XXX\atcoder_python\.devcontainer\docker-compose.yml --profile * config
[3345 ms] name: devcontainer
services:
  python:
    build:
      context: c:\Users\XXX\atcoder_python\.devcontainer
      dockerfile: Dockerfile
    container_name: atcoder
    image: atcoder
    networks:
      default: null
    tty: true
    volumes:
    - type: bind
      source: c:\Users\XXX\atcoder_python
      target: /atcoder_python
      bind:
        create_host_path: true
networks:
  default:
    name: devcontainer_default
[3348 ms] Start: Run: docker inspect --type image python:3.8.2
[5294 ms] local container features stored at: c:\Users\XXX\.vscode\extensions\ms-vscode-remote.remote-containers-0.266.1\dist\node_modules\vscode-dev-containers\container-features
[5295 ms] Start: Run: tar --no-same-owner -x -f -
[5431 ms] Docker Compose override file for building image:
version: "3"

services:
  python:
    build:
      dockerfile: C:\Users\XXX\AppData\Local\Temp\devcontainercli\container-features\0.25.2-1673841118938\Dockerfile-with-features
      args:
        - BUILDKIT_INLINE_CACHE=1
        - _DEV_CONTAINERS_BASE_IMAGE=dev_container_auto_added_stage_label

[5432 ms] Start: Run: docker-compose --project-name atcoder_python_devcontainer -f c:\Users\XXX\atcoder_python\.devcontainer\docker-compose.yml -f c:\Users\XXX\AppData\Roaming\Code\User\globalStorage\ms-vscode-remote.remote-containers\data\docker-compose\docker-compose.devcontainer.build-1673841119076.yml build

[+] Building 12.5s (4/11)
 => [internal] load build definition from Dockerfile-with-features         0.0s
 => => transferring dockerfile: 1.29kB                                     0.0s
 => [internal] load .dockerignore                                          0.0s
 => => transferring context: 2B                                            0.0s
 => [internal] load metadata for docker.io/library/python:3.8.2            3.0s
 => [internal] load build context                                          0.0s
 => => transferring context: 128B                                          0.0s
 => [dev_container_auto_added_stage_label 1/7] FROM docker.io/library/pyt  9.4s
 => => resolve docker.io/library/python:3.8.2@sha256:8c98602bf4f4b2f9b6bd  0.0s
 => => sha256:7232b98bea2caf9b975d81caa6450c1d0a88447e502 2.22kB / 2.22kB  0.0s
 => => sha256:90fe46dd819953eb995f9cc9c326130abe9dd0b39 50.38MB / 50.38MB  7.3s
 => => sha256:35a4f197768941ef308d981a94f6d06fb77b9f2ba89 7.81MB / 7.81MB  2.5s
 => => sha256:8c98602bf4f4b2f9b6bd8def396d5149821c59f8a69 2.36kB / 2.36kB  0.0s
 => => sha256:4f7cd4269fa9900fe43f5c0db2267926ee972cac6ce 8.39kB / 8.39kB  0.0s
 => => sha256:bbc37f14aded2d49bfac62dfa404755c9f1cadfee2 6.29MB / 10.00MB  9.3s
 => => sha256:74e27dc593d49a6d728dfe36976cb1469e076fbf3 46.14MB / 51.83MB  9.3s
 => => extracting sha256:90fe46dd819953eb995f9cc9c326130abe9dd0b3993a998e  1.9s
 => => sha256:4352dcff781953572c12e05ae2fb611066333814 20.97MB / 192.17MB  9.3s

すみません。
以下順不同で試行錯誤した結果、
環境構築2.VSCodeでRemote-Containers: Reopen in Containerを選択で止まらずに立ち上がり、動きました。
・WSLを無効→有効
・PC 再起動
・dockerのContainers,Images,Volumes削除→入れ直し
以下のように便利に使わせていただきます。

vscode@fd9dd43e736c:/atcoder_python/contest/abc285/a$ test
[INFO] online-judge-tools 11.5.1 (+ online-judge-api-client 10.10.1)
[INFO] 3 cases found
[WARNING] GNU time is not available: time

[INFO] sample-1
[INFO] time: 0.180982 sec
[SUCCESS] AC

[INFO] sample-2
[INFO] time: 0.061224 sec
[SUCCESS] AC

[INFO] sample-3
[INFO] time: 0.057682 sec
[SUCCESS] AC

[INFO] slowest: 0.180982 sec  (for sample-1)
[SUCCESS] test success: 3 cases
vscode@fd9dd43e736c:/atcoder_python/contest/abc285/a$ 
ログインするとコメントできます