Python doesn't have true encapsulation unless you drop down to the C level to enforce it separately from the actual runtime. Unofficially, there are conventions on how to mark functions as part of a public interface, but practically speaking, if someone can import your library, they can do whatever they want with it, including adding and changing behavior at runtime. Classes, modules, and even class and function definitions are just hash tables under the hood, and you can change what a given symbol refers to in whatever arbitrary way you want to.
Granted, you shouldn't do very much of that except in some extremely specialized and careful circumstances, but in a language that makes it really easy, you have to be extremely disciplined and often delivery velocity takes precedence over careful planning of what really constitutes a public API.
Practically speaking, putting separate services in literally separate process spaces where the only way they can communicate is via message passing is the only way to really enforce encapsulation.