Python: 'Private' module in a package

冷暖自知 提交于 2019-11-26 16:13:04

问题


I have a package mypack with modules mod_a and mod_b in it. I intend the the package itself and mod_a to be imported freely:

import mypack
import mypack.mod_a

However, I'd like to keep mod_b for the exclusive use of mypack. That's because it exists merely to organize the latter's internal code.

My first question is, is it an accepted practice in Python programming to have 'private' modules like this?

If yes, my second question is, what is the best way to convey this intention to the client? Do I prefix the name with an underscore (i.e. _mod_b)? Or would it be a good idea to declare a sub-package private and place all such modules there?


回答1:


I prefix private modules with an underscore to communicate the intent to the user. In your case, this would be mypack._mod_b

This is in the same spirit (but not completely analogous to) the PEP8 recommendation to name C-extension modules with a leading underscore when it’s wrapped by a Python module; i.e., _socket and socket.




回答2:


The solution I've settled on is to create a sub-package 'private' and place all the modules I wish to hide in there. This way they stay stowed away, leaving mypack's module list cleaner and easier to parse.

To me, this doesn't look unpythonic either.




回答3:


While there are not explicit private keywords there is a convention to have put private functions start with a single underscore but a double leading underscore will make it so others cannot easily call the function from outside the module. See the following from PEP 8

- _single_leading_underscore: weak "internal use" indicator.  E.g. "from M
  import *" does not import objects whose name starts with an underscore.

- single_trailing_underscore_: used by convention to avoid conflicts with
  Python keyword, e.g.

  Tkinter.Toplevel(master, class_='ClassName')

- __double_leading_underscore: when naming a class attribute, invokes name
  mangling (inside class FooBar, __boo becomes _FooBar__boo; see below).

- __double_leading_and_trailing_underscore__: "magic" objects or
  attributes that live in user-controlled namespaces.  E.g. __init__,
  __import__ or __file__.  Never invent such names; only use them
  as documented.

To make an entire module private, don't include it __init__.py file.




回答4:


Python doesn't strictly know or support "private" or "protected" methods or classes. There's a convention that methods prefixed with a single underscore aren't part of an official API, but I wouldn't do this on classes or files - it's ugly.

If someone really needs to subclass or access mod_b, why prevent him/her from doing so? You can always supply a preferred API in your documentation and document in your module that you shouldn't access it directly and use mypack in stead.




回答5:


One thing to be aware of in this scenario is indirect imports. If in mypack you

from mypack._mod_b import foo
foo()

Then a user can

from mypack import foo
foo()

and be none the wiser. I recommend importing as

from mypack import _mod_b
_mod_b.foo()

then a user will immediately see a red flag when they try to

from mypack import _mod_b

As for actual directory structure, you could even extend Jeremy's answer into a _package_of_this_kind package, where anything in that can have any 'access modifiers' on it you like - users will know there be dragons



来源:https://stackoverflow.com/questions/3602110/python-private-module-in-a-package

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!