Most code needs a coin flip sometimes. Maybe you are splitting test traffic, picking a random sample, or building a feature flag. Python makes this trivial, but there is a right way and a few wrong ways to do it.
According to a guide from LiveCodeStream, there are several ways to generate random booleans in Python. Three stand out: `random.getrandbits`, `random.choice`, and the `secrets` module. Each is one or two lines, and each has a use case worth knowing.
At a glance
- `random.getrandbits(1)` is a fast way to get a 50/50 boolean.
- `random.choice([True, False])` reads better and works just as well.
- `random.randint(0, 1)` works but is less efficient.
- The `secrets` module is the right choice when the result must be unpredictable.
- Never use `random` for security tokens, password resets, or anything an attacker could exploit.
Method 1: random.getrandbits(1)
This is the speed-run approach. `random.getrandbits(1)` returns a single random bit, either 0 or 1, and `bool()` turns it into True or False. One line, no allocations, very fast.
“`
Import random
Random_boolean = bool(random.getrandbits(1))
“`
It is the right pick for simulations, tests, and any non-security randomness where you want to be sure the distribution is exactly 50/50.
Method 2: random.choice
This is the readable approach. `random.choice([True, False])` picks one element from a list. Slightly slower than `getrandbits` because it allocates the list, but you almost never care.
“`
Import random
Random_boolean = random.choice([True, False])
“`
Use this when someone else will read your code and you want the intent to be obvious. It also makes it easy to extend to weighted booleans later.
Method 3: random.randint(0, 1)
This works but the guide flags it as less efficient than the other two. `random.randint(0, 1)` returns 0 or 1 with both ends inclusive, and `bool()` converts it. Functionally identical to `getrandbits(1)` in distribution, just a touch slower under the hood.
“`
Import random
Random_boolean = bool(random.randint(0, 1))
“`
Skip it unless you have a reason. The other two are clearer.
When you actually need the secrets module
The `random` module uses a Mersenne Twister-based pseudo-random number generator. It is fast and good enough for games and tests, but it is not cryptographically secure. If someone can observe enough outputs, they can in principle reconstruct the internal state and predict future outputs.
The `secrets` module is designed for exactly this case. It pulls randomness from the operating system's secure source. Use it for anything that affects security, authentication tokens, password reset codes, session IDs, anything an attacker would benefit from predicting.
“`
Import secrets
Random_boolean = bool(secrets.randbelow(2))
“`
The cost is performance. The `secrets` module is noticeably slower, so only reach for it when you actually need unpredictability.
Our analysis
For most everyday code, the choice between `getrandbits` and `choice` is style, not substance. Pick the one that reads better in context. For the rare case where the boolean affects security, reach for `secrets` without hesitation.
Worth watching next: weighted booleans. The guide itself points out that sometimes you do not want 50/50, you might want a different probability tilt. Build a small weighted sampler using the same tools and you can skew outcomes without rewriting logic.
Worked example: feature flag with weighted rollout
Say you are launching a new feature and want to roll it out to a small share of users. You cannot use a simple 50/50 flip. Instead, generate a random number and compare against a threshold that matches your desired share.
“`
Import random
If random.randint(1, 100) <= rollout_percentage:
Enable_new_feature()
“`
That works for a simple percentage gate. If you want the flag itself to be a weighted boolean for later use, `random.choices([True, False], weights=[small_slice, larger_slice])` does it in one call and returns a list. Both approaches let you tune the rollout without rewriting the core logic.
Bottom line
Use `random.choice([True, False])` for readability, `random.getrandbits(1)` for speed, and `secrets.randbelow(2)` when security matters. Do not overthink it. Pick the one that fits the use case and move on.
Key takeaways
- `random.choice([True, False])` is the most readable option.
- `random.getrandbits(1)` is the fastest option.
- Use the `secrets` module for any security-sensitive randomness.
Frequently asked questions
Which is faster, getrandbits or choice?
`getrandbits(1)` is slightly faster because it avoids creating a list. In practice the difference is negligible unless you are calling it millions of times.
Can I use random for password reset codes?
No. Use the `secrets` module for anything security-sensitive. The `random` module is predictable given enough output samples.
How do I generate a weighted boolean in Python?
Use `random.choices([True, False], weights=[true_weight, false_weight])` and take the first element.
Does secrets work on all platforms?
Yes. The `secrets` module draws from the operating system's secure random source, which is available on all major platforms.
Is randint(0, 1) safe to use?
It works for non-security use cases but is less efficient than the other two methods, so the guide suggests avoiding it without a specific reason.