2

I just made a module in python but I don't want people to do this:

import mymodule
mymodule.

and this then shows all methods and variables I added to the module. I just want them to see specified ones because I have many additional ones that are only for internal use.

Grismar
  • 27,561
  • 4
  • 31
  • 54
  • There isn't really a way to do this. There's no real way of hiding objects from introspection in Python. If you want to hide all the methods and variables you used for something, you *could* wrap them inside a function or class, but it's not entirely clear if that's applicable here since you didn't provide any code. If you want help cleaning up your code, try the code review stack exchange site. – ddejohn Jun 03 '22 at 01:13
  • 1
    @ddejohn you're right when limited to just modules, but packages allow what OP is asking for. – Grismar Jun 03 '22 at 01:30
  • Why? Because you want to keep the stuff secret, or just because you don't want to confuse/bother the user with stuff not useful to them? – Kelly Bundy Jun 03 '22 at 01:42
  • @kellybundy I can't speak to OP's reasons, but a very good reason to hide implementation details of a module is because you want the freedom to change how stuff works later, without affecting the code of people that based their application logic on yours. The interface you expose is the interface you end up supporting. – Grismar Jun 03 '22 at 03:16
  • @Grismar Yes, that's a possible reason. Just in case it wasn't clear: I'm not saying they shouldn't do it, I'm just asking why they want it because I think different reasons might have different appropriate solutions. – Kelly Bundy Jun 03 '22 at 03:30
  • @KellyBundy yes actually i just want to make options less for avoid cunfusing and i just did it with movind all functions to a main one – sina janiloran Jun 07 '22 at 15:49

1 Answers1

4

If this is your module mymodule.py:

def expose_this():
    print('yes please')


def but_not_this():
    print('definitely not')

Importing it directly like this:

import mymodule

Gives a user access to mymodule.expose_this() and mymodule.but_not_this(), there's no way to change that, although you could call but_not_this something like _but_not_this instead and many editors would at least warn a user that they are not supposed to access that.

However, the right way to do it would be to create a package. Put your module in a separate folder (called mymodule), and add an __init__.py with this:

from .mymodule import expose_this

Now, if someone imports your package using the same import statement as before, they only have access to mymodule.expose_this()

import mymodule

mymodule.expose_this()  # this works
mymodule.but_not_this()  # this causes an error

There's a lot more to say about creating packages and how to add content, but there's good documentation and tutorials for that out there.

Note: if someone knows the internal structure of your module, they can still access but_not_this() with this:

import mymodule

mymodule.mymodule.but_not_this()

But they'd have to really want to - making it impossible is hard and there's really no point, since someone will be able to get at your code anyway, if they need to. But if you want to make the intent clear, you could rename mymodule.py to _mymodule.py and prefix the functions you don't want exposed with a _ as well - this helps editors to reinforce your intentions with the user.

Grismar
  • 27,561
  • 4
  • 31
  • 54
  • thank you for full Description , i just put my hole methods in a main one and it worked too – sina janiloran Jun 07 '22 at 15:52
  • That's definitely a solution worth mentioning, especially if you're the only user of that code and aren't looking to reuse it in future programs. When you do want to reuse or share code, you should probably have another look at packages - it's not as complicated as it may initially seem. – Grismar Jun 07 '22 at 22:08
  • I've been using approaches of underscore names of "private" resources and set "\_\_all\_\_" to formalize the public ones. But bother me the visibility of all resources imported in my module. Your solution to transform my module into a package solve this. Thank you very much! But the cost to convert a file in 2 files plus a folder may be too big in my bigger projects. Are there any other solution specially to imported resources? I had an idea to put all imports inside an underscored class, for example, "class _i: import re" and use "_i.re" inside my module. What is your opinion about that? – Anselmo Blanco Dominguez Oct 31 '22 at 19:39
  • Don't use (or abuse) classes as modules. There's really no "cost" to having multiple files. It's hardly any slower to compile or run and the overhead on the file system is tiny. The only appreciable 'cost' is that your project will have more files, which may make it harder for you to find things - but that's easily solved by creating an appropriate directory structure. And that cost is offset by not having code in important modules that's only there for the 'plumbing'. Another reason not to do what you're suggesting is the Principle of Least Surprise - users of your module wouldn't expect it. – Grismar Oct 31 '22 at 22:48