0

I've created a Python module file that looks like this:

from abc import ABC, abstractmethod

class Engine(ABC):
    # Rest of class

This gives the unwanted side-effect of a user of my module being able to do this:

import my_module

class SomeClass(my_module.ABC): # Use ABC from my_module!
    # Rest of class

Is there a way to stop a user from accessing ABC and abstractmethod from my module? The only way I can come up with is to change my file structure to something like this:

--my_module/
----__init__.py
----engine.py

and then in __init__.py do from engine import {everything but ABC etc.}. Of course this doesn't actually fix the problem per-se since the user can still do my_module.engine.ABC.

Charanor
  • 810
  • 8
  • 23
  • Why do you want to restrict the access to your abstract class? – Reblochon Masque Nov 06 '17 at 00:35
  • Python has no working security model to reliably prevent some module from accessing objects in other modules in the same Python process. – Michael Butscher Nov 06 '17 at 00:36
  • https://stackoverflow.com/questions/44834/can-someone-explain-all-in-python – Blender Nov 06 '17 at 00:38
  • @ReblochonMasque I don't want to restrict access to my abstract class I want to restrict access to the abc module from my module. – Charanor Nov 06 '17 at 00:40
  • @Blender I've read about __ all __ but as the answers to that question states it only works when you use `from my_module import *`. You can still do `from my_module import ABC` and so on. – Charanor Nov 06 '17 at 00:41
  • okay, my bad - why do you want to restrict access to `ABC` from your module? – Reblochon Masque Nov 06 '17 at 00:47
  • @Charanor: You can delete all your imported objects with `del` at the end of your file if they bug you. `__all__` is useful for the scenario you describe at the end of your question, since the `{everything but ABC etc.}` part can just become `*`. – Blender Nov 06 '17 at 00:50
  • What is the reason makes you wan to restrict access to `ABC` module? – Sraw Nov 06 '17 at 01:20

2 Answers2

2

The typical approach that I've seen is to do something like this:

engine.py:

from abc import ABC, abstractmethod

__all__ = ['Engine']

class Engine(ABC):
    # Rest of class


del ABC
del abstractmethod

__init__.py

from engine import *

Most projects that I've seen don't bother to clean up the imported globals, since they will not be exposed by using __all__ with the __init__.py that imports everything. There's nothing wrong with doing it, though.

If you don't clean them up, the only way a user will be able to see them is if they bypass your module and import those objects from your submodule directly.

Blender
  • 289,723
  • 53
  • 439
  • 496
2

I think the critical problem is why you need to restrict developers?

As python supposes that developers are smart enough to handle security problems about module access and namespace, it doesn't provide any reliable methods to restrict access.

And why you need to restrict person to access ABC module? If you are worrying about variables overriding which may caused by from xxx import *. You can just use __all__ = [...] to specify what you want to export.

requests is a really well-formed library, but it still doesn't make any efforts on unneeded restricting access.

Sraw
  • 18,892
  • 11
  • 54
  • 87
  • And that's really useful for when you want to monkey patch requests without having to copy the entire library and edit it. – Blender Nov 06 '17 at 01:46