ecdsa implements ECDSA and EdDSA in pure Python, with no OpenSSL underneath. That makes it easy to install anywhere and handy for test vectors and teaching, and it is still a dependency of older JOSE stacks such as python-jose. Its maintainers state that it is not designed to resist side-channel attacks, so production signing belongs in pyca/cryptography or coincurve.
Three defaults cause almost every interop failure. The hash defaults to SHA-1: a SigningKey created without hashfunc signs SHA-1 digests, which the check confirmed by verifying the default signature with pyca/cryptography — it passed with SHA-1 and failed with SHA-256. The signature is raw r‖s (64 bytes on P-256), not DER. And VerifyingKey.to_string() returns the bare 64-byte x‖y with no 0x04 prefix, which OpenSSL, Go and WebCrypto do not read as a point.
Signing uses a random nonce unless you call sign_deterministic(), which reproduced the RFC 6979 P-256 test vector. s is left as computed — high about half the time — unless you pick one of the *_canonize encoders, and verification accepts either half. Every encoding choice is made per call through sigencode= and sigdecode=, so the signing and verifying sides must name the same pair; a DER signature passed to the default raw decoder raises BadSignatureError: Malformed formatting of signature.
Curve support is the widest of the Python libraries — P-224 to P-521, secp256k1 and Brainpool — plus Ed25519 and Ed448. Keys come in as SPKI PEM or DER, SEC1 points and raw scalars; to_pem() writes SEC1 EC PRIVATE KEY unless you pass format="pkcs8".
The sample fixes all three defaults at once: SHA-256, a deterministic nonce, and a canonical low-S DER signature. To check a signature it produced against another library, the DER ⇄ raw converter and test vectors are the quickest route.