Skip to main content

Parse PokerNow CSV game logs into structured Python objects.

Project description

pokernow-log-parser

A small, dependency-free Python library that parses PokerNow CSV game logs into clean, structured Python objects.

It focuses on extraction and basic summary statistics — turning the raw text log into hands, actions, boards, shown cards, and per-player net results. It deliberately does not do any plotting or advanced analysis, so you can build whatever analytics you like on top of the structured data.

Features

  • Parses the full PokerNow CSV export format (the entry/at/order columns).
  • Re-sorts the log into chronological order automatically.
  • Extracts, per hand:
    • hand number, hand id, game type, dealer / dead button, timestamp
    • seats and starting stacks
    • blinds, straddles, antes, and missed/missing blinds
    • every action (fold / check / call / bet / raise / show) with street and all-in flag
    • community cards, including run-it-twice second boards
    • shown hole cards and the exporting account's own hand
    • pots collected (with showdown hand descriptions)
    • reconstructed net chip result for every player (verified zero-sum)
    • table position for every player (BTN, SB, BB, UTG, UTG+1, …)
  • Handles mid-hand player ID changes, collapsing them onto one identity.
  • Basic session summary: per-player net results, hands played, VPIP, wins, losses, folds by street, biggest win/loss, and more.
  • Pure standard library — no third-party runtime dependencies.

Installation

pip install pokernow-log-parser

Install the latest unreleased code straight from GitHub:

pip install "git+https://github.com/horris-umich/pokernow-log-parser.git"

Or, from a checkout of this repository:

pip install .

Quick start

from pokernow_parser import PokerNowParser, summarize

log = PokerNowParser().parse_file("my_game.csv")

print(f"{len(log)} hands, players: {log.players}")

# Inspect a single hand
hand = log.hands[0]
print(hand.number, hand.dealer, hand.board)
print(hand.net_results)        # {'Alice @ aaa111': 35.0, 'Bob @ bbb222': -5.0, ...}
print(hand.positions)          # {'Alice @ aaa111': 'BTN', 'Bob @ bbb222': 'SB', ...}
print(hand.position_of("Bob @ bbb222"))   # 'SB'

# Session summary
summary = summarize(log)
for stats in summary.top_winners():
    print(f"{stats.player:>20}  net={stats.net_result:+.0f}  vpip={stats.vpip:.0%}")

You can also parse directly from a string:

from pokernow_parser import parse_string

log = parse_string(open("my_game.csv").read())

Data model

Object Description
GameLog The whole parsed log: .hands, .players, .id_aliases.
Hand One hand: header info, seats, actions, board, pots, net_results, …
Action A single action: player, action (ActionType), street (Street), amount, all_in.
Seat A player's seat number and starting stack.
Pot A pot/portion collected by a player, with optional showdown hand description.
Card A parsed card with rank, suit, and numeric value.
SessionSummary / PlayerStats Aggregated session and per-player statistics.

How net results are computed

Each player's net for a hand is:

net = chips collected + uncalled chips returned − chips committed

Per-street commitment follows PokerNow's "to-amount" convention: a call/bet/raise sets the street total (it already includes any blind posted earlier that street), while dead money (antes, missed/missing blinds) is additive. Across every sample log this reconstruction is exactly zero-sum per hand — a useful correctness invariant that the test suite enforces.

Table positions

Positions are labelled clockwise from the button — BTN, SB, BB, UTG, UTG+1, … — independent of table size. Heads-up is handled (the button is the small blind), as are "dead small blind" hands (the labels shift up by one when no small blind is posted). For the rare "dead button" hands the blind labels remain exact while the button label is a best-effort approximation. Validated against the sample logs, the small- and big-blind posters are labelled SB and BB in 100% of standard hands.

Development

pip install -e ".[dev]"
pytest                 # run the test suite
ruff check src tests   # lint

The tests run against a small, fully sanitized sample log (tests/data/sample_session.csv) containing only fictional names and IDs.

Releasing

Releases are published to PyPI automatically via GitHub Actions using Trusted Publishing (OIDC — no tokens). To cut a release:

  1. Bump version in pyproject.toml and __version__ in src/pokernow_parser/__init__.py, and update CHANGELOG.md.
  2. Create a GitHub Release with a tag like v0.2.0.
  3. The Publish to PyPI workflow runs the tests, builds, and uploads.

License

MIT — see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pokernow_log_parser-0.2.0.tar.gz (19.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pokernow_log_parser-0.2.0-py3-none-any.whl (18.3 kB view details)

Uploaded Python 3

File details

Details for the file pokernow_log_parser-0.2.0.tar.gz.

File metadata

  • Download URL: pokernow_log_parser-0.2.0.tar.gz
  • Upload date:
  • Size: 19.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pokernow_log_parser-0.2.0.tar.gz
Algorithm Hash digest
SHA256 d63dde11be766a03420d408d645e3e2a4d32eb364e7feca996bfe5728faed7a3
MD5 70e5d4cd2f7abe9ae59fd61e1ef950bd
BLAKE2b-256 c330ca1f840741e9920bb4f9e8faa1442b6576b687e8ac59697aadd42b675246

See more details on using hashes here.

Provenance

The following attestation bundles were made for pokernow_log_parser-0.2.0.tar.gz:

Publisher: publish.yml on horris-umich/pokernow-log-parser

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pokernow_log_parser-0.2.0-py3-none-any.whl.

File metadata

File hashes

Hashes for pokernow_log_parser-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 91929637fcd76ed80bec0ef10aaa4111ab04441a94b442aca073f18385a214bb
MD5 69a3996ccb61c1893b86637c03076df5
BLAKE2b-256 41ef380e9db2af107606398544e519f5d391034c90e5d446728c9eae06f2180c

See more details on using hashes here.

Provenance

The following attestation bundles were made for pokernow_log_parser-0.2.0-py3-none-any.whl:

Publisher: publish.yml on horris-umich/pokernow-log-parser

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page