Pythonでパスワードの自動生成、テストデータの作成、トークンの発行など、ランダムな文字列を生成したい場面は開発の現場で数多く出てきます。Pythonにはrandomモジュール・secretsモジュール・uuidモジュールなど、ランダム文字列生成に使えるライブラリが標準で揃っています。
用途によって適切なモジュールの選択が重要です。予測不可能性が求められるパスワードやトークンにはsecretsモジュール、一意な識別子が必要な場合はuuidモジュール、テストデータや一般的な用途にはrandomモジュールと使い分けることが大切です。
この記事では、Pythonでランダム文字列を生成する代表的な方法を、サンプルコードとともにわかりやすく解説していきます。英数字・記号・UUID・パスワード生成まで幅広くカバーしていますので、ぜひ参考にしてください。
Pythonでランダム文字列を生成するにはrandom・secrets・uuidを用途で使い分ける
それではまず、Pythonでランダム文字列を生成するための主要なモジュールと使い分けについて解説していきます。
Pythonでランダム文字列を生成する方法は複数ありますが、セキュリティが必要かどうかと、一意性が必要かどうかで使うモジュールが変わります。
| モジュール | 主な用途 | セキュリティ | 特徴 |
|---|---|---|---|
| random | テストデータ・一般用途 | 低(予測可能) | シンプルで使いやすい |
| secrets | パスワード・トークン生成 | 高(暗号学的安全) | セキュリティ用途に最適 |
| uuid | 一意なID生成 | 中 | 重複しないIDが必要な場面 |
| string | 文字セットの定義 | - | 他モジュールと組み合わせて使用 |
パスワードやAPIトークンなどセキュリティが重要な場面では必ずsecretsモジュールを使いましょう。randomモジュールは予測可能なため、セキュリティが求められる用途には適していません。
stringモジュールで使える文字セット
ランダム文字列を生成する際、どの文字を使うかを定義するのにstringモジュールが便利です。
import string
# stringモジュールで使える文字セット
print(string.ascii_lowercase) # 小文字アルファベット
print(string.ascii_uppercase) # 大文字アルファベット
print(string.ascii_letters) # 大文字+小文字アルファベット
print(string.digits) # 数字
print(string.punctuation) # 記号
# 組み合わせて使う
alphanumeric = string.ascii_letters + string.digits
print(alphanumeric)
# 出力結果:abcdefghijklmnopqrstuvwxyz
# 出力結果:ABCDEFGHIJKLMNOPQRSTUVWXYZ
# 出力結果:abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
# 出力結果:0123456789
# 出力結果:!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~
# 出力結果:abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789
stringモジュールの定数を組み合わせることで、使用する文字の種類を柔軟にカスタマイズできます。
randomモジュールの基本的なランダム文字列生成
import random
import string
# random.choice()で1文字ランダムに選ぶ
chars = string.ascii_letters + string.digits
one_char = random.choice(chars)
print(f"1文字:{one_char}")
# random.choices()でn文字のランダム文字列を生成
length = 10
random_str = "".join(random.choices(chars, k=length))
print(f"10文字:{random_str}")
# 出力結果:1文字:k(毎回変わります)
# 出力結果:10文字:aB3kX9mP2z(毎回変わります)
random.choices()のkパラメータで生成する文字数を指定し、join()で1つの文字列にまとめます。テストデータの生成など、セキュリティが不要な場面での定番パターンです。
random.sampleで重複なしのランダム文字列を生成する
import random
import string
# random.sample():重複なしでランダムに選ぶ
chars = string.ascii_letters + string.digits
# 重複なし8文字
no_dup = "".join(random.sample(chars, 8))
print(f"重複なし8文字:{no_dup}")
# choices()との違いを確認(同じ文字が出るかどうか)
with_dup = "".join(random.choices("abc", k=8))
without_dup = "".join(random.sample("abcdefgh", 8))
print(f"重複あり:{with_dup}")
print(f"重複なし:{without_dup}")
# 出力結果:重複なし8文字:Bx7mK2Rp(毎回変わります)
# 出力結果:重複あり:aacbbcab(同じ文字が出る場合あり)
# 出力結果:重複なし:hgbfaced(すべて異なる文字)
random.choices()は同じ文字が重複して選ばれる可能性がありますが、random.sample()は重複なしで選びます。用途に応じて使い分けましょう。
secretsモジュールで安全なランダム文字列を生成する方法
続いては、セキュリティが求められる場面で使うsecretsモジュールの使い方を確認していきます。
Python 3.6以降で標準搭載されているsecretsモジュールは、暗号学的に安全な乱数を使ってランダム文字列を生成できるモジュールです。パスワード・APIトークン・セッションIDなど、セキュリティが重要な文字列の生成に使いましょう。
secrets.choice()で安全なランダム文字列を生成する
import secrets
import string
# secrets.choice()で暗号学的に安全なランダム文字列
chars = string.ascii_letters + string.digits
# 16文字の安全なランダム文字列
secure_str = "".join(secrets.choice(chars) for _ in range(16))
print(f"安全な16文字:{secure_str}")
# パスワード向け(記号も含む)
chars_with_symbols = string.ascii_letters + string.digits + "!@#$%^&*"
secure_pass = "".join(secrets.choice(chars_with_symbols) for _ in range(12))
print(f"パスワード候補:{secure_pass}")
# 出力結果:安全な16文字:kX9mBp2RzQ7nLv4W(毎回変わります)
# 出力結果:パスワード候補:aB3!kX9@mP2#(毎回変わります)
secrets.choice()はrandom.choice()と同じ使い方ですが、内部で暗号学的に安全な乱数を使用します。パスワード生成には必ずこちらを使いましょう。
secrets.token_hex()でトークンを生成する
import secrets
# token_hex():16進数のランダムトークン
token_hex = secrets.token_hex(16) # 16バイト → 32文字の16進数
print(f"hexトークン:{token_hex}")
# token_urlsafe():URLセーフなBase64トークン
token_url = secrets.token_urlsafe(16)
print(f"URLセーフトークン:{token_url}")
# token_bytes():バイト列のトークン
token_bytes = secrets.token_bytes(16)
print(f"バイトトークン:{token_bytes}")
# 出力結果:hexトークン:a3f8b2c1d4e5f6a7b8c9d0e1f2a3b4c5(毎回変わります)
# 出力結果:URLセーフトークン:Kx9mBp2RzQ7nLv4W(毎回変わります)
# 出力結果:バイトトークン:b'\xa3\xf8\xb2...'(毎回変わります)
secrets.token_hex()やtoken_urlsafe()はAPIキー・セッショントークン・パスワードリセットリンクの生成などに最適なメソッドです。引数にバイト数を指定することで、生成するトークンの長さを調整できます。
条件付きパスワード生成の実装
import secrets
import string
def generate_password(length=12, use_symbols=True):
# 使用する文字セットを構築
chars = string.ascii_letters + string.digits
if use_symbols:
chars += "!@#$%^&*"
while True:
password = "".join(secrets.choice(chars) for _ in range(length))
# 条件チェック:大文字・小文字・数字それぞれ含むか確認
has_upper = any(c.isupper() for c in password)
has_lower = any(c.islower() for c in password)
has_digit = any(c.isdigit() for c in password)
if has_upper and has_lower and has_digit:
return password
# パスワードを3つ生成
for i in range(3):
print(f"パスワード{i+1}:{generate_password(16)}")
# 出力結果:パスワード1:kX9!mBp2RzQ7nLv4(毎回変わります)
# 出力結果:パスワード2:aB3@kX9#mP2$zQ7n(毎回変わります)
# 出力結果:パスワード3:Bx7!mK2@Rp9#nLv4(毎回変わります)
大文字・小文字・数字をすべて含むという条件を満たすまで再生成するパターンです。実際のパスワード生成機能として活用できます。
uuidモジュールで一意なIDを生成する方法
続いては、uuidモジュールを使って一意な識別子(UUID)を生成する方法を確認していきます。
UUIDは「Universally Unique IDentifier」の略で、世界中で重複しない一意なIDを生成するための標準規格です。データベースのプライマリキー・ファイル名・セッション管理など、一意性が求められる場面で広く使われています。
uuid4()で完全ランダムなUUIDを生成する
import uuid
# uuid4():完全ランダムなUUID(最もよく使われる)
uid = uuid.uuid4()
print(uid)
print(type(uid))
# 文字列として取得
uid_str = str(uuid.uuid4())
print(uid_str)
# ハイフンなしの文字列
uid_no_hyphen = uuid.uuid4().hex
print(uid_no_hyphen)
# 出力結果:550e8400-e29b-41d4-a716-446655440000(毎回変わります)
# 出力結果:<class 'uuid.UUID'>
# 出力結果:550e8400-e29b-41d4-a716-446655440000(毎回変わります)
# 出力結果:550e8400e29b41d4a716446655440000(毎回変わります)
uuid4()は乱数を使って生成するUUIDで、実用上ほぼ重複しない一意なIDが得られます。ハイフンあり・なしを用途によって使い分けましょう。
uuid1()でタイムスタンプ付きUUIDを生成する
import uuid
# uuid1():タイムスタンプ+MACアドレスベースのUUID
uid1 = uuid.uuid1()
print(f"UUID1:{uid1}")
# UUID4との比較
uid4 = uuid.uuid4()
print(f"UUID4:{uid4}")
# ファイル名として使う例
filename = f"report_{uuid.uuid4().hex[:8]}.csv"
print(f"ファイル名:{filename}")
# 出力結果:UUID1:xxxxxxxx-xxxx-1xxx-xxxx-xxxxxxxxxxxx(毎回変わります)
# 出力結果:UUID4:xxxxxxxx-xxxx-4xxx-xxxx-xxxxxxxxxxxx(毎回変わります)
# 出力結果:ファイル名:report_a3f8b2c1.csv(毎回変わります)
uuid1()はタイムスタンプとMACアドレスを使うため、生成時刻の情報を含みます。一方uuid4()は完全にランダムなのでプライバシーの観点からも安全です。一般的にはuuid4()の使用が推奨されます。
UUIDをデータベースのIDとして使う
import uuid
# データベースのレコードIDとして使う想定
def create_record(name, value):
return {
"id": str(uuid.uuid4()),
"name": name,
"value": value
}
records = [
create_record("ドラゴンフルーツ", 498),
create_record("アボカド", 298),
create_record("サーモン", 1200),
]
for record in records:
print(f"ID:{record['id'][:8]}... / {record['name']} / {record['value']}円")
# 出力結果:ID:550e8400... / ドラゴンフルーツ / 498円
# 出力結果:ID:a716c446... / アボカド / 298円
# 出力結果:ID:f47ac10b... / サーモン / 1200円
UUIDをレコードIDとして使うことで、複数のデータベースやサービス間でもIDの衝突を避けられます。マイクロサービス構成のシステムなどで特に重宝するパターンです。
ランダム文字列生成の応用パターン
続いては、ランダム文字列生成を活用した実践的な応用パターンを確認していきます。
ランダム文字列の生成は、テストデータの一括生成・ワンタイムコードの発行・ファイル名のユニーク化など、様々な実務シーンで活用できます。
テストデータを一括生成する
import random
import string
def generate_test_user(n):
users = []
for i in range(n):
username = "user_" + "".join(random.choices(string.ascii_lowercase, k=6))
email = username + "@gorilla-test.com"
users.append({"username": username, "email": email})
return users
test_users = generate_test_user(3)
for user in test_users:
print(f"ユーザー名:{user['username']} / メール:{user['email']}")
# 出力結果:ユーザー名:user_kxmpbr / メール:user_kxmpbr@gorilla-test.com
# 出力結果:ユーザー名:user_avznqt / メール:user_avznqt@gorilla-test.com
# 出力結果:ユーザー名:user_plhwde / メール:user_plhwde@gorilla-test.com
テスト用のユーザーデータを自動生成するパターンです。ランダムな文字列をベースにユーザー名やメールアドレスを動的に作成できます。
ワンタイムコード(OTP)を生成する
import secrets
import string
def generate_otp(length=6, digits_only=True):
if digits_only:
# 数字のみのOTP(SMS認証コードなど)
return "".join(secrets.choice(string.digits) for _ in range(length))
else:
# 英数字混合のOTP
chars = string.ascii_uppercase + string.digits
return "".join(secrets.choice(chars) for _ in range(length))
# 6桁数字OTP(SMS認証向け)
print(f"SMS認証コード:{generate_otp(6)}")
# 8桁英数字OTP(メール認証向け)
print(f"メール認証コード:{generate_otp(8, digits_only=False)}")
# 出力結果:SMS認証コード:483920(毎回変わります)
# 出力結果:メール認証コード:K7X2M9PB(毎回変わります)
SMS認証やメール認証で使うワンタイムコードの生成です。セキュリティが必要なためsecretsモジュールを使っています。数字のみか英数字かを引数で切り替えられるようになっています。
ランダムなファイル名を生成する
import secrets
import uuid
# アップロードファイルに一意な名前をつける
def generate_unique_filename(original_name):
# 拡張子を取得
ext = original_name.rsplit(".", 1)[-1] if "." in original_name else ""
# ランダムなファイル名を生成
random_name = secrets.token_hex(8)
return f"{random_name}.{ext}" if ext else random_name
filenames = ["gorilla_photo.jpg", "avocado_recipe.pdf", "keyboard_spec.xlsx"]
for name in filenames:
print(f"{name} → {generate_unique_filename(name)}")
# 出力結果:gorilla_photo.jpg → a3f8b2c1d4e5f6a7.jpg(毎回変わります)
# 出力結果:avocado_recipe.pdf → b8c9d0e1f2a3b4c5.pdf(毎回変わります)
# 出力結果:keyboard_spec.xlsx → c1d2e3f4a5b6c7d8.xlsx(毎回変わります)
ファイルアップロード機能では元のファイル名をそのまま使うとセキュリティリスクになる場合があります。ランダムなファイル名に変換することでパストラバーサルなどのリスクを軽減できます。
まとめ
この記事では、Pythonでランダム文字列を生成する方法について、randomモジュール・secretsモジュール・uuidモジュールの使い方から応用パターンまで幅広く解説しました。
テストデータや一般用途にはrandomモジュール、パスワードやトークンなどセキュリティが必要な場面にはsecretsモジュール、一意なIDが必要な場合はuuidモジュールと使い分けることが大切です。特にパスワード生成にrandomを使うのはセキュリティ上の問題があるため、必ずsecretsモジュールを使いましょう。
OTP生成・テストデータ一括作成・ユニークなファイル名の付与など、今回紹介したパターンは実務でそのまま活用できるものばかりです。ぜひ実際のプロジェクトで試してみてください。