5

My Python package, tinted, finally works. However, when I run dir(tinted), the core.py and sequences.py files exist in the package! I want only the function tint to be included in the package.

Current output of dir(tinted):

['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__', '__version__', 'core', 'sequences', 'tint']

Desired output of dir(tinted):

['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__', '__version__', 'tint']

This is my first time ever uploading a package to PyPi, so please forgive me if I've done anything wrong.

Anyone know how to fix this?

john-hen
  • 4,410
  • 2
  • 23
  • 40
MystPi
  • 116
  • 2
  • 12
  • If you need a function from "core.py" then "core.py" must be included in the pip package (usually a wheel file). "dir" returns the contents of a Python package (if applied to one). This is something else. – Michael Butscher Nov 10 '21 at 22:06
  • @MichaelButscher Could you clarify? – MystPi Nov 10 '21 at 22:10
  • A pip package/wheel file contains the files to install in the Python installation of the user and additional information and commands, e. g. to compile C code. A Python package is a collection of modules and/or other Python packages. Usually it is represented as file system folder containing files and/or other folders. – Michael Butscher Nov 10 '21 at 22:23
  • @MichaelButscher Thank you! Is there any way you could change the package to hide those files, though? – MystPi Nov 10 '21 at 22:42
  • I guess you mean the Python package. See https://stackoverflow.com/questions/44834/can-someone-explain-all-in-python which can also be applied to the `__init__.py` of a package, not only modules. But I don't know if it changes the behavior of "dir", too. Why exactly do you want to modify "dir" result? – Michael Butscher Nov 10 '21 at 22:48
  • 1
    FYI: Your github link does not work. – Warren Weckesser Nov 11 '21 at 00:36
  • @WarrenWeckesser It's public now; thanks for the info! – MystPi Nov 11 '21 at 12:10

1 Answers1

2

Let's say you have your Python package in a folder named tinted. You have a function named tint defined in module core.py inside that folder. But you want to expose that function at the top level of the package's namespace. Which is good practice for important functions, they should be at the top level.

Then in __init__.py you would have this:

from .core import tint

(Or from tinted.core import tint if you happen to use absolute imports.)

However, as you have noted, this also puts the core module into the package's top-level namespace:

>>> import tinted
>>> dir(tinted)
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__',
'__name__', '__package__', '__path__', '__spec__', 'core', 'tint']

If you want to keep that namespace squeaky-clean, you can remove the internal module after the import in __init__.py. Like so:

from .core import tint
del core

Then:

>>> dir(tinted)
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__',
'__name__', '__package__', '__path__', '__spec__', 'tint']

This is however not commonly done. Even packages in Python's standard library don't usually remove these kind of imports. For example, the logging package imports threading and just leaves it there. Though sometimes they do clean up a bit. Like the copy module, which does del types, weakref at the end. So there's nothing wrong with it either.

In this case, the object was a function. Just note that, when it's a class, you cannot completely hide the package structure anyway. Consider this example from the popular Pandas library:

>>> import pandas
>>> pandas.DataFrame
<class 'pandas.core.frame.DataFrame'>
john-hen
  • 4,410
  • 2
  • 23
  • 40
  • One thing I noticed with my package is that you can still access `core` and `sequences` with dot notation, but they **are** hidden from the namespace. I guess that's because its more "pythonic" that way. – MystPi Nov 11 '21 at 12:26
  • 1
    That's just how the import mechanism works. Just like you can do `from pandas import core` even when you never imported `pandas`. The import mechanism looks for the actual files, it doesn't care about namespaces. – john-hen Nov 11 '21 at 12:31