0

I'm struggling with my first Python package + script project using setuptools. Here's a skeleton of my setup.py:

setuptools.setup(
    name=<PROJECT>,
    packages=[<PACKAGE_NAME>],
    scripts=['bin/<PACKAGE_NAME>.py'],
    python_requires='>=3',
)

My package is in package_name/ and my script, which has the same base name as the package, is in bin/package_name.py. The script does from package_name import *. There are no dependencies.

When I run python3 setup.py install, it succeeds. Thereafter, when I do import package_name in a Python console, it succeeds. But when I run the script from the command line, it fails with a NameError on the first reference to a component from the package. I've reproduced the same error on Mac OS X and Linux.

Why does it fail this way, but doesn't throw an ImportError? How can I fix my script or my setup.py?

1 Answer 1

1

has the same base name as the package

That's exactly the problem. When you run package_name.py and the script imports package_name Python tries to import it from that script because it's the first package_name.py in sys.path (Python automatically prepends script's directory to sys.path).

Rename the script to package_name. Or even better create __main__.py in your package and use entry_points:

setup(
    …
    entry_points={
        'console_scripts': [
            'package_name = package_name.__main__:main'
        ]
    },
    …
)

That way setuptools create the script package_name for you automatically.

See an example in my mimedecode.

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you - that solved the problem, and taught me something about Python's import order. Placing command-line scripts in __main__.py inside the package seems like it break the separability of library and client. I'd say that wasn't great practice in C, but I don't know Python as well. Is that the preferred way to distribute such a package (library + its own client)?
Yes. Or, if it's a one-module (not-package) library it usually has its own main() function, protected with if __name__ == '__main__'. Even modules in Python library have these. Example: zipfile.py.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.