paiza.IO の API を優しく触ってみる

# はじめに

私の初めての記事なので優しく見てください．

[paiza.IO](https://paiza.io/) は色んな言語のコードを実行できる素晴らしいサイトです．このサイトには API が用意されていて簡単に自分のプログラムに組み込むことができます．

この記事のゴールは色んな言語をコマンドラインで実行できるようにする事です．具体的には，

```py:hello.py
print('hello world')
```

というファイルを作って

```
$ ./paiza.py python3 hello.py
```

とすると

```
--stdout--
hello world

--build_stderr--
None
--stderr--

```

と表示されるようにする事です．

## 前提知識

- Python の基本的な文法

## 著者の環境

- macOS Catalina 10.15.7
- Python 3.8.1

# 説明

`paiza.py` というファイル名で作っていきます．

ファイル名で実行できるように最初に Shebang を付けます．

```py
#!/usr/bin/env python
```

必要なモジュールを import します．requests ライブラリはまだインストールしていない方は `pip install requests` してください．

```py
import sys
import time

import requests
```

次にコマンドライン引数から言語とソースファイル名を指定します．

```py
# 実行する言語
language = sys.argv[1]
# 実行するファイルを読み込む
with open(sys.argv[2], 'r') as f:
    source = f.read()
```

早速これらを paiza.IO の API に投げてみます．API の仕様は[ここ](http://api.paiza.io/docs/swagger/#!/runners/)で確認できるので色々試してみてください．

/runners/create で ID を取得，/runners/get_status でプログラムが終了したか確認，/runners/get_details で結果を取得という流れになりますが，２秒経てばタイムアウトするので今回は簡単のためにプログラムの終了を確認せず２秒後に結果を取得しようと思います．

まずは /runners/create で ID を取得します．`'input'` になにか送ると標準入力が使えますが今回は使いません．

```py
url = 'http://api.paiza.io'
# API に送る JSON を辞書で指定
params = {
    'source_code': source,
    'language': language,
    'input': '',
    'api_key': 'guest',
}
# /runners/create に POST リクエストを送る
response = requests.post(
    url + '/runners/create',
    json=params
)
id = response.json()['id']
```

２秒間待ちます．

```py
time.sleep(2.0)
```

/runners/get_details で結果を取得します．

```py
# API に送る JSON を辞書で指定
params = {
    'id': id,
    'api_key': 'guest',
}
# /runners/get_details に GET リクエストを送る
response = requests.get(
    url + '/runners/get_details',
    json=params
)
# 結果を辞書にする
result = response.json()
```

最後に結果を print します．

```py
print('--stdout--')
print(result['stdout'])
print('--build_stderr--')
print(result['build_stderr'])
print('--stderr--')
print(result['stderr'])
```

ファイル名で実行できるように権限を付けます．

```
$ chmod +x paiza.py
```

# 実行してみる

## Hello world

```py:hello.py
print('hello world')
```

```
$ ./paiza.py python3 hello.py
--stdout--
hello world

--build_stderr--
None
--stderr--

```

他の言語でも OK です．

<details><summary>言語一覧</summary><div>

- c
- cpp
- objective-c
- java
- kotlin
- scala
- swift
- csharp
- go
- haskell
- erlang
- perl
- python （古いバージョンなので注意）
- python3
- ruby
- php
- bash
- r
- javascript
- coffeescript
- vb
- cobol
- fsharp
- d
- clojure
- elixir
- mysql
- rust
- scheme
- commonlisp
- nadesiko
- typescript
- plain
</div></details>

```c:hello.c
#include <stdio.h>

int main(void) {
    printf("hello world\n");
    return 0;
}
```

```
$ ./paiza.py c hello.c
--stdout--
hello world

--build_stderr--

--stderr--

```

## コンパイルエラーの場合

コンパイルエラーは Python では起こり得ないので C で書きます．

```c:build_error.c
#include <stdio.h>

int main(void) {
    printf("hello world\n")
    return 0;
}
```

```
$ ./paiza.py c build_error.c
--stdout--
None
--build_stderr--
Main.c:4:28: error: expected ';' after expression
    printf("hello world\n")
                           ^
                           ;
1 error generated.

--stderr--
None
```

## ランタイムエラーの場合

```py:error.py
print(1 / 0)
```

```
$ ./paiza.py python3 error.py
--stdout--

--build_stderr--
None
--stderr--
Traceback (most recent call last):
  File "Main.py", line 1, in <module>
    print(1 / 0)
ZeroDivisionError: division by zero
```

## タイムアウトの場合

```py:timeout.py
while True:
    pass
```

```
$ ./paiza.py python3 timeout.py
--stdout--

--build_stderr--
None
--stderr--

```

# まとめ

paiza.IO の API，簡単に使えていいですね！ぜひ色々なところに応用させてみてください．

<details><summary>できたコード</summary><div>

```py:paiza.py
#!/usr/bin/env python

import sys
import time

import requests

url = 'http://api.paiza.io'
# 実行する言語
language = sys.argv[1]
# 実行するファイルを読み込む
with open(sys.argv[2], 'r') as f:
    source = f.read()
# API に送る JSON を辞書で指定
params = {
    'source_code': source,
    'language': language,
    'input': '',
    'api_key': 'guest',
}
# /runners/create に POST リクエストを送る
response = requests.post(
    url + '/runners/create',
    json=params
)
id = response.json()['id']

time.sleep(2.0)

# API に送る JSON を辞書で指定
params = {
    'id': id,
    'api_key': 'guest',
}
# /runners/get_details に GET リクエストを送る
response = requests.get(
    url + '/runners/get_details',
    json=params
)
# 結果を辞書にする
result = response.json()

print('--stdout--')
print(result['stdout'])
print('--build_stderr--')
print(result['build_stderr'])
print('--stderr--')
print(result['stderr'])
```
</div></details>

# 参考にしたページ
- [paiza.IOのAPIを使って競プロっぽいアプリを作ってみた](https://qiita.com/M1YamA00/items/4d96f0df609ad246314f)
- [Requests: 人間のためのHTTP](https://requests-docs-ja.readthedocs.io/en/latest/)