Duck Typing describes the philosophy of the quote "If it looks like a duck and it quacks like a duck, then it probably is a duck." In Python, despite the prevalence of this philosophical abstraction, I really never used Duck Typing much at all. Whenever I thought I would find a use for it, there would be some small blemish on the Duck API that broke the build. The only time I really found a use for it was during monkey-patching or some other fairly abusive maneuver. In Rust, by comparison, each duck is accompanied by a contract that it at least behaves like a duck in some minimal fashion. This is incredibly useful, and is the underlying philosophy behind Rust's trait system.
A trait, much like a duck API, describes a number of methods and attributes on a type. At compile time these traits are attached to each concrete type and then any implementors are permitted to pass around trait objects in place of concrete types. In Practice, these ducks are everywhere, even in the standard library. Duck-typing is in-fact very practical, however it really really helps to be able to enforce things like whether to implement a .len() method or a .length() method or a .size() method. In Python those were the simple things that would break the duck API. Usually just even small spelling differences would turn a duck into a Tanager. I guess that I'm just glad to be on this side of the fence now.