プログラミング演習・14章版 第11章 実行環境・ファイル・モジュール
教材コード

実行環境・ファイル・モジュール

プログラムは,書く場所,実行する場所,データを置く場所の関係を理解すると安定して動く.本章では Notebook とスクリプト,利用者の入力,ファイルとCSV,自作モジュールを扱う.

Notebookとスクリプトを実行する

Notebook(notebook)はセルごとに実行できる環境です.スクリプト(script)は,保存したプログラムを上から順に実行するファイルです.Google Colab はブラウザでNotebookを動かす環境の一つです.

Notebook はセルの実行順で状態が変わります.画面上で上のセルに書かれた変数でも,そのセルをまだ実行していなければ参照できません.再現性を確認するには実行状態を初期化し,上から順に実行します.スクリプトでは python hello.py のように保存済みファイルを指定し,通常は先頭から処理が進みます.

Notebook のセルでは,データ確認や試行を短い単位で実行できます.画面上で先に書いた命令でも,実行していなければ変数はまだ作られません.スクリプトは,保存した処理を先頭から続けて実行するのに適します.

chapter-11_code_1.py
x = 4
print(x + 1)
実行結果の例
5

1行目をNotebookのセル1,2行目をセル2に分けて順に実行すると5が表示されます.同じ2行を hello.py に保存して python hello.py で実行しても,先頭から順に実行されます.

セル2だけを先に実行すると,その実行環境に x がまだ存在しない場合は NameError になります.Notebookで結果が不思議なときは実行順と残っている状態を確認します.

そのまま演習Notebookとスクリプトを実行する · そのまま演習

そのまま演習:セル1を x = 6 に変えて実行し,次にセル2を実行します.

ヒントを見る

x の代入を変更すると、その後の x + 1 が使う値も変わります。加える1を変える課題ではありません。

演習の解説を見る

解説:セル2の x + 1 は新しい値6を使い,7を表示します.

虫食いNotebookとスクリプトを実行する · 虫食い

あいさつの表示は残し、その次に実行中のモジュール名 __name__ を表示する行を追加してください。このエディタではプログラムを直接実行するため、あいさつと __main__ の2行になります。ファイル名を文字列として書かず、変数 __name__ を使います。

端末で実行するコマンドの例です。右側では、その実行結果をPythonで確かめます。

___ hello.py
ヒントを見る

__name__ は実行器が用意する変数です。直接実行したプログラムの名前と、保存するファイル名を区別してください。表示には変数を渡します。

演習の解説を見る

このエディタはプログラムを直接実行するため __name__ は __main__ です。あいさつに続けてその変数を表示すると、こんにちは と __main__ の2行になります。

状態を初期化して再実行する

Notebookでは,見えているセルの順番と実際の実行順が異なることがあります.作業を他者が再現できるように,セルを最初から順に実行した結果を確認します.

chapter-11_code_4.py
count = 0
count = count + 1
print(count)
実行結果の例
1

1行目で0を代入し,2行目で1増やし,3行目で1を表示します.2行目と3行目のセルだけを再実行すると,状態が残っている場合は2と表示されます.1行目から再実行すれば1に戻る.

Notebookで以前の実行結果だけを見て「プログラムが正しい」と判断しません.セルを編集したら再実行します.結果を共有する前には,状態を初期化して上から実行し,途中で未定義の変数に依存しないことを確認します.

そのまま演習状態を初期化して再実行する · そのまま演習

そのまま演習:count = count + 1 のセルをもう一度実行し,値を表示します.

ヒントを見る

上から順に二つの更新を実行します。どちらの右辺も、その時点で count に保存されている値を使います。

演習の解説を見る

解説:直前の値が1なら2となります.初期化セルを先に実行し直せば,次の結果は再び1です.

虫食い状態を初期化して再実行する · 虫食い

虫食い演習:毎回0から数え直す最初の行 count = ___ を補います.

ヒントを見る

更新を始める前の count を、まだ一度も数えていない値に初期化します。その後、二度増やして表示する行も追加します。

演習の解説を見る

解説:空欄は 0 です.初期化は状態をそろえるために必要です.

コマンドライン引数とキーボード入力

コマンドライン引数(command-line argument)は起動時に渡す文字列です.input() はプログラムの実行中にキーボードから文字列を受け取ります.

sys.argv の先頭 sys.argv[0] は通常スクリプト名であり,利用者が続けて指定した引数は sys.argv[1:] で得られます.input() の戻り値は常に文字列です.整数として計算するなら int による変換が必要であり,不正な入力では ValueError が起こりうる.

コマンドライン引数は実行コマンドに続けて指定し,input() は実行途中で質問して受け取ります.どちらも利用者から届いた値は文字列です.キーボードで「20」と入力しても,数の計算に使うには整数へ変えます.

chapter-11_code_6.py
age = int(input("年齢: "))
print(age + 1)
実行結果の例
年齢: 20
21

1行目は質問を表示して入力を待ち,入力文字列 "20" を整数20に変換します.2行目は20に1を足して表示します.実行結果の 20 は利用者が入力した例です.

chapter-11_code_8.py
import sys
print(sys.argv[1:])

この2行を args.py に保存し,python args.py A B と起動すると ['A', 'B'] を表示します.1行目は sys を読み,2行目はスクリプト名を除いた部分を表示します.

そのまま演習コマンドライン引数とキーボード入力 · そのまま演習

年齢に0を入力したとき、翌年の年齢1を表示するプログラムに変更してください。

ヒントを見る

入力した0を整数にしてから翌年の年齢を求めます。入力の表示と、計算結果の表示を区別してください。

演習の解説を見る

解説:int("0") は整数0であり,1を足して1を表示します.

虫食いコマンドライン引数とキーボード入力 · 虫食い

虫食い演習:入力文字列を整数へ変換する関数名を補います.

chapter-11_code_9.py
n = ___(input("整数: "))
ヒントを見る

入力は文字列として返ります。整数として計算できるように、入力を受け取る式の外側で型を変換します。

演習の解説を見る

解説:空欄は int です.変換しないまま n + 1 とすると,文字列と整数を足そうとしてエラーになります.

input() が返す "20" と整数20は別の値です.input("年齢: ") + 1 は文字列と整数を足せず失敗します.int(input("年齢: ")) + 1 とします.ただし "二十" のような入力は int に変換できず,ValueError になります.

実行前の引数と実行中の入力を比べる

sys.argv の各要素も文字列です.数として使う場合は input() の結果と同じように変換します.たとえば python plus.py 5 で起動し,次の内容を実行します.

chapter-11_code_10.py
import sys
n = int(sys.argv[1])
print(n + 1)
実行結果の例
6

1行目は sys を読みます.2行目は起動時に指定した最初の値 "5" を整数5に変えます.3行目は6を出します.値を付けずに起動すると sys.argv[1] が存在せず,IndexError になります.

そのまま演習実行前の引数と実行中の入力を比べる · そのまま演習

そのまま演習:python plus.py 0 で実行します.

ヒントを見る

sys.argv の2番目にある引数を整数に変換します。プログラム名の要素は変更しません。

演習の解説を見る

解説:0を整数に変換して1を足し,1を表示します.

虫食い実行前の引数と実行中の入力を比べる · 虫食い

虫食い演習:n = ___(sys.argv[1]) の空欄を補います.

ヒントを見る

起動引数は文字列です。整数として扱うための変換を行い、引数を読むための準備と表示の行も追加します。

演習の解説を見る

解説:空欄は int です.起動時の引数も文字列で届く.

with,文字コード,パス

プログラムからファイルへ書き込み,読み戻す流れ

ファイル(file)は実行後も残るデータです.with open(...) を使うと,処理が終わる際にファイルを閉じる.文字コード(character encoding)は文字を保存するための符号の規則であり,本書の例では UTF-8 を使います.

open の "w" は書き込み用に開き,既存の内容を置き換える."r" は読み込みであり,省略時の既定値です.with はコンテキスト管理により,途中で例外が起きても後片付けを行います.相対パス(relative path)は現在の作業ディレクトリを基準に解釈されます.プログラムの保存場所を基準にするとは限りません.

with はノートを開いて書き,作業が終わったら閉じる係を付ける書き方です."w" は新しく書き直す指定なので,前の内容を残したいときには注意します.相対パスは「今いる場所から見た道順」です.

chapter-11_code_12.py
with open("sample.txt", "w", encoding="utf-8") as f:
    f.write("こんにちは\n")

with open("sample.txt", encoding="utf-8") as f:
    print(f.read())
実行結果の例
こんにちは

1行目はUTF-8の書き込み用としてファイルを開きます.2行目は文字列と改行を保存します.4行目は同じファイルを読み込み用に開きます.5行目は全体を読み,print で表示します.保存した改行に加え,print 自身も改行するため,表示例には空行があります.

chapter-11_code_14.py
from pathlib import Path
p = Path("data") / "sample.csv"
print(p.name)
実行結果の例
sample.csv

1行目は Path を読みます.2行目はディレクトリ名とファイル名を結ぶ.3行目は最後のファイル名だけを表示します.Path はパスの構成を扱うが,この3行だけでファイルを作成するわけではありません.

"w" は既存ファイルの内容を消してから書きます.意図しない上書きを避けるため,実験には練習用のファイル名を使います.ファイルが見つからないときは現在の作業ディレクトリとパスの綴りを確認します.

そのまま演習with,文字コード,パス · そのまま演習

sample.csv に 'A\n' を UTF-8 で書き込み、読み戻した内容を表示してください。

ヒントを見る

書き込む前に親フォルダを用意し、同じパスをUTF-8で読み戻します。文字列に含まれる改行と print の追加改行が重ならないようにします。

演習の解説を見る

解説:ファイルには A と改行が保存されます.読んで表示すると A が現れます.

虫食いwith,文字コード,パス · 虫食い

虫食い演習:UTF-8で読み込む引数名を補います.

chapter-11_code_16.py
with open("sample.txt", ___="utf-8") as f:
    print(f.read())
ヒントを見る

utf-8 は読み込む文字の符号化方式です。空欄は開くモードではなく、文字コードを指定するキーワード引数名です。

演習の解説を見る

解説:空欄は encoding です.保存時と同じ文字コードを指定します.

上書きと追記を区別する

"w" で開くたびに古い内容は消える.行を増やしたい場合は "a" で追記します.次の例は最初に一行を書き,続けて一行追加します.

chapter-11_code_17.py
with open("memo.txt", "w", encoding="utf-8") as f:
    f.write("一行目\n")
with open("memo.txt", "a", encoding="utf-8") as f:
    f.write("二行目\n")
with open("memo.txt", encoding="utf-8") as f:
    print(f.read(), end="")
実行結果の例
一行目
二行目

1行目と2行目は古い内容を置き換えて「一行目」を書きます.3行目と4行目は末尾に「二行目」を足します.5行目は読んで,6行目は内容を表示します.end="" を指定するのは,読み込んだ内容の末尾にすでに改行があるためです.

そのまま演習上書きと追記を区別する · そのまま演習

そのまま演習:"a" で「三行目」を追加し,読み戻す.

ヒントを見る

最初の書き込みでファイルを作り直し、その後は末尾に追加します。三行目も、読み込みを始める前に保存します。

演習の解説を見る

解説:三つの行が順に表示されます."a" は以前の二行を消しません.

虫食い上書きと追記を区別する · 虫食い

虫食い演習:末尾へ追記する指定 open("memo.txt", "___", encoding="utf-8") を補います.

ヒントを見る

二度目に開くときは最初の1行を残し、末尾に2行目を足します。内容を消して作り直すモードを選ばないでください。

演習の解説を見る

解説:空欄は a です.w では上書きになります.

CSVを読み書きする

次の2図は同じ構図です.図11.1で集計の道筋を考えてから,図11.2の書き込みを確認します.

CSVを集計する:書き込む前
CSVを集計する:書き込んだ後

CSVファイル(comma-separated values file)は行と列でデータを保存する形式です.カンマを含む値や引用符を扱うため,単純な split(",") より標準ライブラリの csv を使います.

csv.reader は各行を文字列のリストとして返します.数値の列は int などで変換してから計算します.csv.writer で書く場合は newline="" を渡すと余分な空行を避けられます.読み書き時には文字コードを揃える.

CSVは表計算の表を文字で保存したものです.読み込むと,1行が一つのリストになります.点数の「80」も最初は文字なので,足し算する前に数へ直します.

chapter-11_code_19.py
import csv
with open("scores.csv", "w", newline="", encoding="utf-8") as f:
    writer = csv.writer(f)
    writer.writerow(["name", "score"])
    writer.writerow(["A", 80])

with open("scores.csv", newline="", encoding="utf-8") as f:
    for row in csv.reader(f):
        print(row)
実行結果の例
['name', 'score']
['A', '80']

1行目は csv を読みます.2行目は書き込み用に開きます.3行目は書き手を作ります.4行目は見出し,5行目は1件のデータを書きます.7行目は読み込み用に開き直します.8行目と9行目は各行を表示します.読み戻した80が '80' と表示されるのは,CSVから得た値が文字列だからです.

そのまま演習CSVを読み書きする · そのまま演習

そのまま演習:writer.writerow(["B", 70]) を加えて読み戻す.

ヒントを見る

見出しと各データは別々のCSV行です。追加するデータも書き込み用 with の中で保存し、読み込む順序を確認します。

演習の解説を見る

解説:見出し,Aの行,Bの行の3行が順に表示されます.Bの点数も文字列 '70' です.

虫食いCSVを読み書きする · 虫食い

虫食い演習:CSVへ一行を書くメソッド名を補います.

chapter-11_code_21.py
writer.___(["C", 90])
ヒントを見る

リスト一つをCSVの1行として書き込みます。複数行のリストをまとめて受け取るメソッドとは区別してください。

演習の解説を見る

解説:空欄は writerow です.一行の値をリストで渡す.

csv.reader が返す "80" に 10 を足そうとすると TypeError になります.整数の点数として扱う場合は int(row[1]) に直します.また見出し行の "score" は整数にできないため,見出しを読み飛ばす.

見出しとデータ行を分けて集計する

直前に作った scores.csv を読み,点数の合計を求めます.ここではAの1件だけなので合計は80となります.

chapter-11_code_22.py
import csv
goukei = 0
with open("scores.csv", newline="", encoding="utf-8") as f:
    reader = csv.reader(f)
    header = next(reader)
    for row in reader:
        goukei += int(row[1])
print(header, goukei)
実行結果の例
['name', 'score'] 80

1行目は csv を読みます.2行目は合計を0にします.3行目はCSVを開きます.4行目は行を読む道具を作ります.5行目の next は見出しを取り出します.6行目は残りのデータ行を繰り返します.7行目は点数の文字列を整数に変えて足します.8行目は見出しと合計を表示します.見出しだけでデータがない場合,合計は0です.

そのまま演習見出しとデータ行を分けて集計する · そのまま演習

そのまま演習:Bの70点の行を追加してから集計します.

ヒントを見る

見出しを一度だけ取り出し、残りのデータ行の点数を足します。追加した行も、文字列から整数へ変換して集計します。

演習の解説を見る

解説:Aの80点とBの70点を足し,goukei は150となります.

虫食い見出しとデータ行を分けて集計する · 虫食い

虫食い演習:CSVの点数列を足す式 goukei += ___(row[1]) を補います.

ヒントを見る

row[1] の80には引用符があり、文字列です。goukei は整数なので、加える前に同じ数値の型へ変換します。

演習の解説を見る

解説:空欄は int です.CSVの列は文字列で読み込まれます.

モジュールを再利用する

別のPythonファイルにある関数を読み込む

モジュール(module)はPythonの定義をまとめたファイルです.別のファイルから import して,関数などを再利用できます.

tools.py の関数 double は,import tools 後に tools.double として参照します.名前空間を分けることで,同名の関数との衝突を避けられます.読み込みに失敗するときはファイル名,保存場所,Pythonが探すパスを調べます.

よく使う計算を別のノート tools.py に書いておくと,別のプログラムからノートを開いて使えます.tools.double(3) は「toolsというノートのdoubleを使う」という読み方です.

tools.py の内容:

chapter-11_code_24.py
def double(x):
    return x * 2

同じ場所に保存する main.py の内容:

chapter-11_code_25.py
import tools
print(tools.double(3))
実行結果の例
6

tools.py の1行目は関数名と引数を定め,2行目は2倍した値を返します.main.py の1行目は自作モジュールを読み,2行目はその関数へ3を渡し,返された6を表示します.

そのまま演習モジュールを再利用する · そのまま演習

そのまま演習:tools.double(5) を表示して結果を確かめる.

ヒントを見る

tools.py の関数定義は2倍のままです。モジュールの準備を残し、呼び出し時に渡す値を変更します。

演習の解説を見る

解説:5を2倍した10が表示されます.関数の定義を main.py に複写する必要はありません.

虫食いモジュールを再利用する · 虫食い

虫食い演習:自作モジュールの関数呼び出しを完成させる.

chapter-11_code_27.py
import tools
print(___.double(4))
ヒントを見る

関数は読み込んだモジュールの属性として呼び出します。空欄は関数名ではなく、import 文で使ったモジュール名です。

演習の解説を見る

解説:空欄は tools です.tools.double(4) は8を返します.

import tools.py とは書きません.import tools と書き,ファイル名の拡張子を外す.また,同じ作業フォルダに tools.py 以外の tools という名前のファイルやフォルダがあると,意図しないものを読み込むことがあります.

関数定義と実行部分を分ける

自作モジュールの先頭にある通常の文は,import されたときにも実行されます.関数を定義する部分と,ファイルを直接起動したときの試行を分けるには次の形を使います.

chapter-11_code_28.py
def double(x):
    return x * 2

if __name__ == "__main__":
    print(double(3))

この内容を tools.py に保存して直接起動すると6が表示されます.main.py から import tools すると,関数定義は利用できるが,下の print は実行されません.1行目と2行目が関数定義,4行目が直接起動かどうかの判定,5行目が直接起動時だけの試行です.

そのまま演習関数定義と実行部分を分ける · そのまま演習

tools.py 相当の関数定義と実行部分を分けたまま、double(4) の結果を表示してください。

ヒントを見る

直接実行の条件を残し、関数に渡す値だけを変えます。double の式と新しい引数を対応させて予想します。

演習の解説を見る

直接実行では __name__ が __main__ なので条件の内側を実行します。double に4を渡すため、4 × 2 の結果8を1行で表示します。

虫食い関数定義と実行部分を分ける · 虫食い

虫食い演習:直接起動の判定 if __name__ == "___": を補います.

ヒントを見る

直接実行されたプログラムに付く特別な名前を比較します。空欄は変数名ではなく、引用符内の比較対象の文字列です。

演習の解説を見る

解説:空欄は __main__ です.両側の下線も名前の一部です.

Notebookでは実行順,スクリプトでは保存先と起動方法を確かめる.ファイルは with で開き,文字コードと作業ディレクトリを意識します.CSVには csv,再利用する定義にはモジュールを使います.

用語を確かめる

Notebook

読み:のーとぶっく.英語:notebook.ノートを意味する語で,セルに試行を記録します.関連語:セル,実行順.

スクリプト

読み:すくりぷと.英語:script.台本を意味する語です.関連語:プログラム,端末.

コマンドライン引数

読み:こまんどらいんひきすう.英語:command-line argument.起動する命令の行に続けて書く値です.関連語:sys.argv,引数.

ファイル

読み:ふぁいます.英語:file.文書を綴じた束に由来します.関連語:読み込み,保存.

文字コード

読み:もじこーど.英語:character encoding.文字を符号へ対応させる方式です.関連語:UTF-8,復号.

相対パス

読み:そうたいぱす.英語:relative path.現在の位置に対して定まる道順です.関連語:作業ディレクトリ,絶対パス.

CSV

読み:しーえすぶい.英語:comma-separated values.カンマで区切られた値に由来します.関連語:行,列,csv.reader.

モジュール

読み:もじゅーる.英語:module.組み合わせられる部品という意味です.関連語:import,関数.

用語を確かめる:言葉とコードの動きを結び付けます

知識

ファイルから読み出す操作は、読み取り位置を進めながら文字を受け取る操作です。withは、ブロックを抜けるときに対象を閉じる仕組みを利用します。この例ではディスク上へファイルを作らず、io.StringIOでメモリー上の文字列をファイルと同じように読みます。実ファイルではopenで対象のファイルを開きます。

import io

f = io.StringIO("こんにちは\nPython\n")
with f:
    print(f.readline(), end="")
print(f.closed)
そのまま演習用語を確かめる:言葉とコードの動きを結び付けます

メモリー上の2行から1行目だけを読み、続いて対象が閉じられたかを表示します。実行前に行数と各行の内容を予想し、そのまま実行してください。その後「出力例」を開いて比較します。入力はありません。readlineの返値に含まれる改行を使うため、最初のprintはend=""とします。

出力例
こんにちは
True
ヒントを見る

読み出す文字列には改行も含まれます。表示命令が追加する末尾の文字を確認し、ブロックを抜けた後の対象の状態も予想してください。

演習の解説

readlineは最初の「こんにちは」と末尾の改行を返します。printのendを空文字列にするため余分な改行は増えません。withのブロックを抜けるとfが閉じられ、f.closedはTrueになります。2行目のPythonは読み取っていません。閉じた後にreadlineを再実行するとエラーになります。

虫食い用語を確かめる:言葉とコードの動きを結び付けます

___の1か所に、ブロックを抜けると読み取り対象を閉じる構文のキーワードを補ってください。他の行は変更せず、こんにちはとTrueを別々の行へ表示してください。

import io

f = io.StringIO("こんにちは\nPython\n")
___ f:
    print(f.readline(), end="")
print(f.closed)
ヒントを見る

readlineは1行分を改行も含めて返します。最後のprintは字下げされていないので、ブロックを抜けた後に実行されます。その時点で読み取り対象が開いたままかを考えてください。

虫食いの解説
import io

f = io.StringIO("こんにちは\nPython\n")
with f:
    print(f.readline(), end="")
print(f.closed)

空欄には with が入ります。readlineは最初の「こんにちは」と末尾の改行を返します。printのendを空文字列にするため余分な改行は増えません。withのブロックを抜けるとfが閉じられ、f.closedはTrueになります。2行目のPythonは読み取っていません。閉じた後にreadlineを再実行するとエラーになります。

図で理解する

ファイル入出力
ファイル入出力
モジュールの再利用
モジュールの再利用
CSVを集計する:考える前
CSVを集計する:考える前
CSVを集計する:書き込んだ後
CSVを集計する:書き込んだ後

練習して確かめる

Colab と Notebook の基本

知識

Notebook はコードを小さなセルに分けて実行します。Shift+Enter で現在のセルを実行し、結果はセルの直下に現れます。上のセルで作った変数は、ランタイムを再起動すると消える。

chapter-11_code_29.py
x = 2
print(x + 3)
そのまま演習Colab と Notebook の基本 · そのまま演習

セルの x を6に変え、結果9を1行で表示してください。

ヒントを見る

セルで代入する値と、その次の計算に使われる値を対応させます。x への代入を変更し、足す数はそのまま残してください。

演習の解説

セルの x を6に変えると、続く x + 3 は6 + 3です。出力は9の1行になります。

虫食いColab と Notebook の基本 · 虫食い

x = 2 は残します。加える数の空欄を埋め、計算した結果5を1行で表示してください。

chapter-11_code_30.py
x = 2
print(x + ___)
ヒントを見る

先に x へ2を代入します。問題で指定された表示結果になるように、後で加える値を考えます。

虫食いの解説
chapter-11_code_31.py
x = 2
print(x + 3)

3 を補います。上のセルが未実行なら x は未定義になります。

Python スクリプトを実行する

知識

コードを .py ファイルに保存し、端末で python ファイル名.py と入力すると上から順に実行されます。Notebook と違い、実行ごとに新しいプロセスが始まる。

chapter-11_code_32.py
# hello.py
print('こんにちは')
そのまま演習Python スクリプトを実行する · そのまま演習

あいさつの表示を残し、その次に __name__ が '__main__' と等しい場合だけ『直接実行』を表示する if 文を追加してください。このエディタの実行では、あいさつと『直接実行』の2行になります。

ヒントを見る

直接実行した場合の __name__ を比較条件にします。条件の下に置く表示の行にはインデントが必要です。あいさつの表示は条件の外に残します。

演習の解説

直接実行では __name__ が __main__ なので if の中も実行されます。出力は、こんにちは と 直接実行 の2行です。モジュールとして読み込む場合は条件の内側の表示を実行しません。

虫食いPython スクリプトを実行する · 虫食い

空欄を埋め、コードを実行してください。

chapter-11_code_33.py
# hello.py
___('こんにちは')
ヒントを見る

括弧内のあいさつを画面へ表示するための組み込み関数を使います。引用符の中身は変更しません。

虫食いの解説
chapter-11_code_34.py
# hello.py
print('こんにちは')

print を補います。

コマンドライン引数

知識

スクリプトは実行時にコマンドラインから値を受け取れます。sys.argv[0] はスクリプト名で、以降が引数。引数は文字列なので数値として使うなら変換します。

chapter-11_code_35.py
import sys
print(sys.argv[1:] if len(sys.argv) > 1 else [])
そのまま演習コマンドライン引数 · そのまま演習

引数 A と B を受け取った一覧と引数の個数2を、それぞれ1行で表示してください。

ヒントを見る

引数一覧からプログラム名を除いた範囲を使います。同じ範囲を表示し、その長さも次の行に表示します。

演習の解説

A と B が文字列のリストとして表示されます。

虫食いコマンドライン引数 · 虫食い

空欄を埋め、コードを実行してください。

chapter-11_code_36.py
import sys
print(sys.___[1:])
ヒントを見る

sys の属性には、起動時の引数を順に並べたリストがあります。スライス[1:]は先頭のプログラム名を除きます。

虫食いの解説
chapter-11_code_37.py
import sys
print(sys.argv[1:])

argv を補います。

入力と型変換

知識

input はキーボード入力を文字列で返します。計算に使う数値なら int または float で変換します。変換できない入力では ValueError になります。

chapter-11_code_38.py
age = int(input('年齢: '))
print(age + 1)
そのまま演習入力と型変換 · そのまま演習

入力した年齢の翌年と翌々年の年齢を、それぞれ1行で表示してください。

ヒントを見る

入力は一度だけ読み込みます。同じ age から翌年と翌々年を計算し、二つの結果を別々の行へ表示します。

演習の解説

input の結果は文字列なので、int で整数に変えてから 1 を足します。

虫食い入力と型変換 · 虫食い

空欄を埋め、コードを実行してください。

chapter-11_code_39.py
x = ___(input('整数: '))
print(x * 2)
ヒントを見る

input の結果を整数にしてから2倍します。文字列のままでは繰り返しになるので、変換する型を確かめます。

虫食いの解説
chapter-11_code_40.py
x = int(input('整数: '))
print(x * 2)

int を補います。

with と文字コード

知識

ファイルは with で開くとブロック終了時に閉じられます。日本語のテキストでは encoding='utf-8' を明示すると環境差を減らせる。

chapter-11_code_41.py
with open('sample.txt', 'w', encoding='utf-8') as f:
    f.write('こんにちは\n')
そのまま演習with と文字コード · そのまま演習

ファイルに書く既存の with 文を残し、そのあとに sample.txt を UTF-8 で読む with 文を追加してください。読み込んだ内容を表示し、ファイル内にある末尾の改行だけを使います。print の end を空文字列にし、空行を追加しないでください。出力は『こんにちは』の1行です。

ヒントを見る

read で受け取る文字列にはファイルへ書いた改行も含まれます。print が通常付ける改行を重ねないように、表示の終わり方を指定してください。

演習の解説

書き込み用の with を抜けてから読み込むため、内容がファイルに保存された状態で読めます。ファイルには末尾の改行があるので、print の end を空文字列にしてその改行だけを使います。出力は、こんにちは の1行で、空行はありません。

虫食いwith と文字コード · 虫食い

空欄を埋め、コードを実行してください。

chapter-11_code_42.py
with open('sample.txt', 'r', encoding='utf-8') as f:
    print(f.___())
ヒントを見る

ファイルの一部ではなく、残りの内容を文字列としてまとめて取得します。空欄はファイルオブジェクトの読み込みメソッドです。

虫食いの解説
chapter-11_code_43.py
with open('sample.txt', 'r', encoding='utf-8') as f:
    print(f.read())

read を補います。

ディレクトリとパス

知識

相対パスは現在の作業ディレクトリを基準に解釈されます。pathlib.Path はファイル名や親ディレクトリを扱いやすくします。

chapter-11_code_44.py
from pathlib import Path
p = Path('data') / 'sample.csv'
print(p.name)
そのまま演習ディレクトリとパス · そのまま演習

例を実行し、p.parent も表示します。

ヒントを見る

name は末尾のファイル名、parent はその親のパスです。同じ Path から二つの属性を順番に表示します。

演習の解説

p.name は sample.csv、p.parent は data。

虫食いディレクトリとパス · 虫食い

空欄を埋め、コードを実行してください。

chapter-11_code_45.py
from pathlib import Path
p = Path('data') / 'sample.csv'
print(p.___)
ヒントを見る

data という親の部分ではなく、最後の sample.csv だけを取り出す属性です。メソッドではないので括弧は付けません。

虫食いの解説
chapter-11_code_46.py
from pathlib import Path
p = Path('data') / 'sample.csv'
print(p.name)

name を補います。

CSV の読み書き

知識

CSV は行と列を区切ったテキスト形式。値にカンマや改行が入ることがあるため、単純な split より csv.reader を使います。

chapter-11_code_47.py
import csv
with open('sample.csv', newline='', encoding='utf-8') as f:
    for row in csv.reader(f):
        print(row)
そのまま演習CSV の読み書き · そのまま演習

import csv の次、既存の読み込み用 with 文の前に、sample.csv を UTF-8・書き込みモード・newline='' で作る with 文を追加してください。csv.writer で見出し ['name', 'score'] とデータ ['A', 80] の2行を書きます。既存の csv.reader と行ごとの print は残し、読み取った2つのリストを各1行で表示してください。CSVから読み取る数値列は文字列になります。空行は加えません。

ヒントを見る

書き込みは読み込みより先に行います。CSVの見出しとデータを別の行として writer に渡し、読み込んだ点数が数値ではなく文字列になる点を確認してください。

演習の解説

sample.csv に見出しとデータを書いてから、同じファイルを csv.reader で読みます。出力は ['name', 'score'] と ['A', '80'] の2行です。CSVは文字列として読み込むため、点数にも引用符が付いて表示されます。

虫食いCSV の読み書き · 虫食い

空欄を埋め、コードを実行してください。

chapter-11_code_48.py
import csv
with open('sample.csv', newline='', encoding='utf-8') as f:
    for row in csv.___(f): print(row)
ヒントを見る

ファイルの各行を文字列のリストへ変えるCSVの読み取り器を作ります。書き込み用の処理とは区別してください。

虫食いの解説
chapter-11_code_49.py
import csv
with open('sample.csv', newline='', encoding='utf-8') as f:
    for row in csv.reader(f): print(row)

reader を補います。

モジュールを作る

知識

自作の関数を別ファイルに保存すると import で再利用できます。モジュール名はファイル名から .py を除いたもの。

chapter-11_code_50.py
# tools.py に def double(x): return x*2
# 別のファイルで
import tools
print(tools.double(3))
そのまま演習モジュールを作る · そのまま演習

tools.py の double を読み込み、double(5) の結果を表示してください。

ヒントを見る

tools.py にある double の定義を確認します。呼び出しの引数だけを変更し、モジュール名を付けた呼び出しを残してください。

演習の解説

tools.double は渡された値を2倍にして返します。引数を5に変えたため、5 × 2 の結果10を1行で表示します。

虫食いモジュールを作る · 虫食い

空欄を埋め、コードを実行してください。

chapter-11_code_51.py
import tools
print(tools.___(3))
ヒントを見る

tools.py に定義された関数名を確認します。モジュール名は既に書かれているので、空欄には属性としての関数名を置きます。

虫食いの解説
chapter-11_code_52.py
import tools
print(tools.double(3))

double を補います。

章末演習(10問)

ここには解答を載せていません。

  1. 章末演習章末演習 1

    【基本】with 文と open を使い,一時フォルダの中のテキストファイル memo.txt に3行を UTF-8 で書き込み,同じプログラムの中で読み戻して行番号付きで表示してください。

    入力

    キーボード入力なし。書き込む内容はプログラムの中で fruits = ["りんご", "みかん", "ぶどう"] として用意します。

    処理条件

    • 保存先は tempfile.TemporaryDirectory() で作った一時フォルダとし,ファイルのパスは pathlib.Path と / 演算子で組み立てる。
    • 書き込み・読み込みの両方で with open(パス, モード, encoding="utf-8") as f: の形を使います。Path.write_text や Path.read_text で代用しません。
    • 書き込みでは fruits の各要素の末尾に改行文字を付けて1行ずつ書きます。
    • 読み込みではファイルオブジェクトを for 文で1行ずつ回し,行末の改行文字を取り除いてリストに入れます。表示には必ず読み戻したリストを使い,fruits を直接表示しません。
    • 行番号は enumerate で1から付ける。行数は読み戻したリストの要素数(len 可)とします。

    出力

    • 4行を出力します。1〜3行目は「行番号: 内容」(半角コロンの直後に半角空白1つ),4行目は「行数: 3」。数字とコロンは半角。
    • 上記以外の行(見出し,入力の確認表示,デバッグ用の print など)は出力しません。

    実行例

    1: りんご
    2: みかん
    3: ぶどう
    行数: 3
    
    ヒントを見る

    書き込むときは改行を自分で付ける必要があり,読み込んだ各行の末尾には改行が残っています。それぞれどの段階で付け外しするかを考えましょう。

  2. 章末演習章末演習 2

    【基本】コマンドライン引数 sys.argv と同じ形のリストを受け取り,数の部分を足し算した式を文字列で返す関数 main(argv) を作ってください。ブラウザ実行器ではコマンドラインを使えないので,リストを直接渡して試します。

    入力

    キーボード入力なし。次の4つのリストを,この順に main に渡す。

    ["add.py", "3", "4"]
    ["add.py", "10", "20", "30"]
    ["add.py", "5", "-2"]
    ["add.py"]
    

    処理条件

    • argv[0] はスクリプト名,argv[1] 以降は整数を表す文字列(負数を含むことがある)とします。整数として読めない文字列は与えません。
    • 数が1つ以上あるときは,argv[1:] の文字列をそのまま「 + 」(+ の前後に半角空白)でつなぎ,続けて「 = 」と合計を付けた文字列を返します。合計は各要素を int に変換して求める(sum の使用は可,eval は不可)。
    • 数が1つもないとき(argv の要素がスクリプト名だけのとき)は「使い方: 」,argv[0],「 数 数 ...」をつないだ文字列を返します。スクリプト名は "add.py" と書き込まず argv[0] から取る。
    • main の中では print せず,戻り値を呼び出し側で print します。sys の import は不要。

    出力

    • 4行を出力します。記号・数字・空白はすべて半角。「使い方」の行のコロンの後ろは半角空白1つ,「...」は半角ピリオド3つ。
    • 上記以外の行(見出し,入力の確認表示,デバッグ用の print など)は出力しません。

    実行例

    3 + 4 = 7
    10 + 20 + 30 = 60
    5 + -2 = 3
    使い方: add.py 数 数 ...
    
    ヒントを見る

    argv の先頭は計算に使わない値です。表示に使う部分(元の文字列)と計算に使う部分(整数)を分けて考えましょう。

  3. 章末演習章末演習 3

    【基本】キーボードから1行を読み,空白区切りの整数の最小値・最大値・平均値を表示してください。

    入力

    キーボードから1行を入力します。半角空白で区切った整数が0個以上並ぶ。行頭・行末・数の間に余分な半角空白が入ってもよいでしょう。整数以外の文字は入力しません。

    処理条件

    • input() で1行を読みます。input の括弧の中に案内文字列は書きません。
    • 関数 summarize_line(line) を定義し,読んだ文字列を渡す。関数は整数が1つ以上あれば (最小値, 最大値, 平均値) のタプルを,1つもなければ None を返します。
    • 文字列は split()(引数なし)で区切り,各要素を int に変換します。min・max・sum・len の使用は可。statistics などのモジュールは使いません。
    • 平均値は関数の中では丸めず,表示するときに書式指定 :.2f で小数点以下2桁にします。

    出力

    • 1行だけ出力します。整数が1つ以上あれば「最小 値 最大 値 平均 値」(各語と値の間は半角空白1つ),なければ「データなし」。
    • 入力欄に表示される入力値は実行結果に含めません。上記以外の行(見出し,入力の確認表示,デバッグ用の print など)は出力しません。

    実行例

    実行例1 入力欄に入れる値:

      12 7 30  
    

    出力:

    最小 7 最大 30 平均 16.33
    

    実行例2 入力欄に入れる値:

    5 5 5
    

    出力:

    最小 5 最大 5 平均 5.00
    

    実行例3 入力欄に入れる値:

    -4 10
    

    出力:

    最小 -4 最大 10 平均 3.00
    

    実行例4 入力欄に入れる値:(何も入力せずに確定する) 出力:

    データなし
    
    ヒントを見る

    input() が返すのは常に文字列です。区切った後の要素の型と,要素が1つもない場合に平均の計算で何が起きるかを確かめてから書きましょう。

  4. 章末演習章末演習 4

    【応用】pathlib を使い,フォルダ内のファイルを拡張子で絞り込む操作と,パスを部品に分ける操作を行ってください。

    入力

    キーボード入力なし。作るファイル名はプログラムの中で names = ["a.txt", "b.csv", "c.txt", "notes.md"] として用意します。調べるパスは p = Path("data/report_2026.csv") とします。

    処理条件

    • tempfile.TemporaryDirectory() で作った一時フォルダの中に,names の4つの空ファイルを Path.touch() で作ります。
    • 一時フォルダの Path に対して glob("*.txt") を呼び,得られた各 Path の .name を取り出して名前の昇順に並べたリストを作る(sorted 可)。os.listdir や文字列の endswith で代用しません。
    • p の name・stem・suffix・parent を半角空白区切りで1行に表示します。parent は as_posix() で / 区切りにしてから表示します。
    • with_suffix(".txt") で拡張子を変えたパスを作り,as_posix() で表示します。

    出力

    • 3行を出力します。1行目は .txt ファイル名のリストを print したもの,2行目は p の4項目,3行目は拡張子を変えたパス。
    • Windows でも区切り文字は / で表示します。上記以外の行(見出し,入力の確認表示,デバッグ用の print など)は出力しません。

    実行例

    ['a.txt', 'c.txt']
    report_2026.csv report_2026 .csv data
    data/report_2026.txt
    
    ヒントを見る

    glob が返すのは文字列ではなく Path です。比べたり並べたりする前に,どの属性を取り出すかを決めましょう。stem と suffix は name をどこで分けたものかも確かめましょう。

  5. 章末演習章末演習 5

    【応用】csv モジュールで商品表を CSV ファイルに書き込み,読み戻して商品ごとの小計と合計金額を計算してください。

    入力

    キーボード入力なし。書き込むデータはプログラムの中で次のように用意します。

    rows = [["商品", "単価", "数量"], ["ノート", 120, 3], ["ペン", 80, 5], ["消しゴム", 60, 2]]
    

    処理条件

    • 一時フォルダ(tempfile.TemporaryDirectory())の items.csv に csv.writer で rows を書き込む。open には newline="" と encoding="utf-8" を指定します。
    • 同じファイルを csv.DictReader で読み戻す。読み戻した最初の行の "単価" が文字列であることを assert isinstance(..., str) で確かめる(成り立てば何も表示されない)。
    • 小計は int に変換した単価×数量とします。合計は for 文の中で小計を足し込んで求めます。rows の数値を直接計算に使いません。

    出力

    • 4行を出力します。1〜3行目は CSV の順に「商品名 小計」,4行目は「合計 金額」。区切りは半角空白1つ,数字は半角,円などの単位は付けません。
    • 上記以外の行(見出し,入力の確認表示,デバッグ用の print など)は出力しません。

    実行例

    ノート 360
    ペン 400
    消しゴム 120
    合計 880
    
    ヒントを見る

    DictReader が各行をどんな形で返すか(キーは何か,値の型は何か)を先に確かめましょう。書き込んだときに整数だった値が,読み戻すと何になっているかが鍵です。

  6. 章末演習章末演習 6

    【応用】同じ文字列でも,保存する文字コードによってファイルのバイト数が変わることを確かめてください。

    入力

    キーボード入力なし。文字列はプログラムの中で text = "日本語abc" とします。

    処理条件

    • 一時フォルダ(tempfile.TemporaryDirectory())の utf8.txt には encoding="utf-8" で,sjis.txt には encoding="shift_jis" で text を書き込む(Path.write_text 可)。この順で処理します。
    • ファイルのバイト数は Path.stat().st_size で,先頭3バイトは read_bytes() の結果をスライスして求めます。len(text.encode(...)) で代用しません。
    • 書き込んだときと同じ文字コードで読み戻し(read_text 可),2つとも text と等しいかを調べて真偽値1つにまとめる。

    出力

    • 3行を出力します。1・2行目は「文字コード名: バイト数 バイト 先頭3バイト」。先頭3バイトは bytes 型の値を print したときの表記(b'...')のまま表示します。各要素の区切りは半角空白1つ。
    • 3行目は「どちらも元に戻った: True」(戻らなければ False)。上記以外の行(見出し,入力の確認表示,デバッグ用の print など)は出力しません。

    実行例

    utf-8: 12 バイト b'\xe6\x97\xa5'
    shift_jis: 9 バイト b'\x93\xfa\x96'
    どちらも元に戻った: True
    
    ヒントを見る

    書いた後のファイルの大きさはファイル側の情報から取り出します。漢字とローマ字で1文字あたりのバイト数がそれぞれの文字コードでどう違うかを予想してから,実行結果と比べましょう。

  7. 章末演習章末演習 7

    【応用】標準ライブラリのモジュールを import して,開始日から締切日までの日数と,それを週単位に切り上げた週数を求める関数 plan(start, deadline) を作ってください。

    入力

    キーボード入力なし。次の4組の (開始日, 締切日) を,この順に plan に渡す。日付は "YYYY-MM-DD" 形式の文字列で,締切日は開始日と同じ日かそれより後とします。

    ("2026-10-01", "2026-11-15")
    ("2026-12-24", "2027-01-07")
    ("2026-10-01", "2026-10-08")
    ("2026-10-04", "2026-10-04")
    

    処理条件

    • import math と from datetime import date の2つの書き方をどちらも使います。
    • 文字列は date.fromisoformat で日付に変換し,日付どうしの引き算の結果から日数を整数で取り出します。
    • 週数は math.ceil(日数 / 7) で求めます。// と条件分岐を組み合わせた切り上げで代用しません。日数が0なら週数も0とします。
    • plan は (日数, 週数) のタプルを返し,表示は呼び出し側で行います。

    出力

    • 4行を出力します。各行は「開始日 → 締切日: N日 (M週)」。矢印は「→」(U+2192)でその前後に半角空白1つ,コロンと丸括弧は半角,「日」と「週」は全角で数字の直後に空白を入れません。
    • 上記以外の行(見出し,入力の確認表示,デバッグ用の print など)は出力しません。

    実行例

    2026-10-01 → 2026-11-15: 45日 (7週)
    2026-12-24 → 2027-01-07: 14日 (2週)
    2026-10-01 → 2026-10-08: 7日 (1週)
    2026-10-04 → 2026-10-04: 0日 (0週)
    
    ヒントを見る

    日付どうしを引いた結果は整数ではなく,日数を表す属性を持つ値です。切り上げは,ちょうど割り切れる場合と1日だけはみ出す場合の両方で確かめましょう。

  8. 章末演習章末演習 8

    【複合】成績 CSV を読み,学生ごとの平均点の列を加えた新しい CSV を書き出してから,それを読み戻して確かめてください。

    入力

    キーボード入力なし。元データはプログラムの中で次の文字列 source として用意し,一時フォルダの scores.csv に UTF-8 で書き込む(Path.write_text 可)。

    source = "氏名,数学,英語,情報\nAoi,80,70,90\nRen,65,85,76\nMio,95,90,98\n"
    

    処理条件

    • scores.csv は csv.reader で読みます。見出し行の末尾に "平均" を加え,各学生の行の末尾に3科目の平均点を加えた表を作ります。
    • 平均点は int に変換した3科目の合計÷3を,組み込み関数 round(値, 1) で小数第1位に丸めた値とする(sum・len 可)。
    • 表を一時フォルダの result.csv に csv.writer で書き出し(open に newline="" と encoding="utf-8"),もう一度 csv.reader で読み戻す。表示には読み戻したデータを使います。
    • ファイルはすべて tempfile.TemporaryDirectory() の中に作ります。

    出力

    • 4行を出力します。1〜3行目は CSV の順に「氏名 平均点」(半角空白1つで区切る。平均点は読み戻した文字列のまま,小数第1位まで)。4行目は result.csv の見出し行をリストとして print したもの。
    • 上記以外の行(見出し,入力の確認表示,デバッグ用の print など)は出力しません。

    実行例

    Aoi 80.0
    Ren 75.3
    Mio 94.3
    ['氏名', '数学', '英語', '情報', '平均']
    
    ヒントを見る

    見出し行とデータ行は扱いが違うので,読み込んだリストのどこまでが見出しかを先に分けましょう。数値として書き出した平均点が,読み戻したときにどんな型になっているかにも注意します。

  9. 章末演習章末演習 9

    【複合】ログファイルを1行ずつ読み,ERROR の行の行番号と内容を集めた要約を別のファイルに書き出し,その要約ファイルを読み戻して表示してください。

    入力

    キーボード入力なし。ログはプログラムの中で次の文字列 log として用意し,一時フォルダの app.log に UTF-8 で書き込む(Path.write_text 可)。

    log = "09:00 INFO 起動\n09:05 ERROR 接続失敗\n09:06 INFO 再試行\n09:07 ERROR 認証失敗\n09:10 INFO 終了\n"
    

    処理条件

    • app.log は with open(..., encoding="utf-8") で開き,ファイルオブジェクトを enumerate(..., start=1) で1行ずつ回す。readlines や read で全体を一度に読みません。
    • 空白で区切った2番目の語がちょうど "ERROR" の行を ERROR の行とします。
    • ERROR の行ごとに「行番号: 行の内容(行末の改行を除く)」を作り,最後に「ERROR 件数件」を加えて,1行ずつ改行で終わる形で summary.txt に with open(..., "w", encoding="utf-8") で書きます。ERROR の行が0件なら summary.txt は「ERROR 0件」の1行だけになります。
    • summary.txt を読み戻した内容をそのまま表示する(読み戻し方は自由)。集めたリストを直接 print しません。

    出力

    • 3行を出力する(summary.txt の内容)。行番号の後ろは半角コロンと半角空白1つ。最終行は「ERROR 2件」(ERROR と数字の間は半角空白1つ,「件」は全角)。
    • 最後の行の後ろに空行を加えません。上記以外の行(見出し,入力の確認表示,デバッグ用の print など)は出力しません。

    実行例

    2: 09:05 ERROR 接続失敗
    4: 09:07 ERROR 認証失敗
    ERROR 2件
    
    ヒントを見る

    行番号は人が数える番号にそろえます。summary.txt の各行が改行で終わっていると,読み戻した内容を表示するとき print の改行と重ならないよう工夫が必要です。

  10. 章末演習章末演習 10

    【複合】コマンドラインから実行する集計プログラムを関数 main(argv) として作り,CSV から下限点以上の学生を点数の高い順に取り出してください。

    入力

    キーボード入力なし。テスト用に,一時フォルダの class.csv に次の内容を UTF-8 で書き込む(Path.write_text 可)。

    氏名,点数
    Aoi,72
    Ren,58
    Mio,91
    Sora,60
    

    そのうえで,class.csv のパスを str に変換した値を path として,次の3つの argv で main を呼ぶ。

    ["report.py", path]
    ["report.py", path, "--min", "70"]
    ["report.py", path, "--min", "100"]
    

    処理条件

    • argv の形は ["report.py", CSVファイルのパス, "--min", 下限点] で,"--min" とその値は省略できます。省略したときの下限点は 60 とします。"--min" がある場合は必ず直後に整数の文字列があります。
    • "--min" の位置はリストの index で調べ,その次の要素を int に変換します。argparse は使いません。
    • CSV は csv.DictReader で読み,点数(int に変換)が下限点「以上」の行だけを残す。
    • 残った行を点数の高い順に並べる(sort または sorted の key 引数と reverse 引数を使う)。同点のときは CSV の順を保つ。
    • main は氏名のリストを返し,print は呼び出し側で行います。該当者がいなければ空リストを返します。

    出力

    • 3行を出力します。各行は main が返したリストを print したもの(3行目は [])。
    • 上記以外の行(見出し,入力の確認表示,デバッグ用の print など)は出力しません。

    実行例

    ['Mio', 'Aoi', 'Sora']
    ['Mio', 'Aoi']
    []
    
    ヒントを見る

    まず下限点を決め,次に絞り込み,最後に並べ替えるという順で組み立てましょう。ちょうど下限点と同じ点数の学生が含まれるかどうかで,比較演算子の選び方を確かめられます。