Python: 'Private' module in a package

前端 未结 5 776
小蘑菇
小蘑菇 2020-12-05 06:23

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 free

相关标签:
5条回答
  • 2020-12-05 06:46

    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.

    0 讨论(0)
  • 2020-12-05 06:48

    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.

    0 讨论(0)
  • 2020-12-05 06:51

    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.

    0 讨论(0)
  • 2020-12-05 07:03

    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

    0 讨论(0)
  • 2020-12-05 07:05

    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.

    0 讨论(0)
提交回复
热议问题