Created a PyPI package and it installs, but when run it returns an import error

StackOverflow https://stackoverflow.com/questions/23164482

  •  06-07-2023
  •  | 
  •  

سؤال

I've created a simple package and was able to publish it in PyPI. It's file struc is:

DaysGrounded\
DaysGrounded\setup.py
DaysGrounded\setup.cfg
DaysGrounded\requirements.txt
DaysGrounded\MANIFEST.in
DaysGrounded\daysgrounded\
DaysGrounded\daysgrounded\__init__.py
DaysGrounded\daysgrounded\__main__.py
DaysGrounded\daysgrounded\cli.py
DaysGrounded\daysgrounded\gui.py
DaysGrounded\daysgrounded\shared.py

I installed it in another machine and run c:\Python34\Scripts\daysgrounded.exe, but it returns the following error: Traceback (most recent call last): File "C:\Python34\lib\runpy.py", line 171, in _run_module_as_main "main", mod_spec) File "C:\Python34\lib\runpy.py", line 86, in _run_code exec(code, run_globals) File "C:\Python34\Scripts\daysgrounded.exe__main__.py", line 5, in File "C:\Python34\lib\site-packages\daysgrounded__main__.py", line 12, in import cli ImportError: No module named 'cli'

You can find the app in https://github.com/jcrmatos/DaysGrounded and https://pypi.python.org/pypi?name=daysgrounded&version=0.0.8&:action=display

What am I doing wrong? Is it in setup.py?

#!/usr/bin/env python
# -*- coding: latin-1 -*-

from __future__ import (absolute_import, division, print_function,
                        unicode_literals)

from setuptools import setup, find_packages
#import py2exe

from daysgrounded import *

setup(
    name=__title__,
    version=__version__,

    description=__desc__,
    long_description=open('README.txt').read(),
    #long_description=(read('README.txt') + '\n\n' +
    #                  read('CHANGES.txt') + '\n\n' +
    #                  read('AUTHORS.txt')),
    license=__license__,
    url=__url__,

    author=__author__,
    author_email=__email__,

    keywords=__keywords__,
    classifiers=__classifiers__,

    packages=find_packages(exclude=['tests*']),
    #packages=__packages__,

    entry_points=__entrypoints__,
    install_requires=open('requirements.txt').read(),
    #install_requires=open('requirements.txt').read().splitlines(),

    include_package_data=True,
    package_data=__pkgdata__,

    #console=['daysgrounded\\__main__.py']
)


Or is it in __init__.py?

"""Manage child(s) grounded days."""

__all__ = [
    '__title__', '__version__',
    '__desc__', '__license__', '__url__',
    '__author__', '__email__',
    '__copyright__',
    '__keywords__', '__classifiers__',
    #'__packages__',
    '__entrypoints__', '__pkgdata__'
]

__title__ = 'daysgrounded'
__version__ = '0.0.8'

__desc__ = __doc__.strip()
__license__ = 'GNU General Public License v2 or later (GPLv2+)'
__url__ = 'https://github.com/jcrmatos/DaysGrounded'

__author__ = 'Joao Matos'
__email__ = 'jcrmatos@gmail.com'

__copyright__ = 'Copyright 2014 Joao Matos'

__keywords__ = 'days grounded'
__classifiers__ = [
        'Development Status :: 4 - Beta',
        'Environment :: Console',
        'Environment :: Win32 (MS Windows)',
        'Intended Audience :: End Users/Desktop',
        'Intended Audience :: Developers',
        'Natural Language :: English',
        'Natural Language :: Portuguese',
        'License :: OSI Approved :: GNU General Public License v2 or later (GPLv2+)',
        'Operating System :: OS Independent',
        'Programming Language :: Python',
        'Programming Language :: Python :: 2.7',
        'Programming Language :: Python :: 3.4',
        'Topic :: Other/Nonlisted Topic',
        # Use below to prevent any unwanted publishing
        #'Private :: Do Not Upload'
    ]

#__packages__ = ['daysgrounded']

__entrypoints__ = {
        'console_scripts': ['daysgrounded = daysgrounded.__main__:main'],
        #'gui_scripts': ['app_gui = daysgrounded.daysgrounded:start']
    }

__pkgdata__ = {'daysgrounded': ['*.txt']}
#__pkgdata__= {'': ['*.txt'], 'daysgrounded': ['*.txt']}

Thanks,

JM

هل كانت مفيدة؟

المحلول

This is due to the difference between the three ways of invoking a python package:

  1. python daysgrounded
  2. python daysgrounded/__main__.py
  3. python -m daysgrounded

If you try each of these on your project you'll notice that the third method doesn't work, which is exactly the one runpy uses. The reason it doesn't work is because your sys.path is incorrect, because python adds daysgrounded/ to your sys.path for the first two ways, but not the third.

In order for all three ways to work, you have to make sure that your sys.path is correct, and there are two ways of doing this.

If you want to be able to do import cli, sys.path should be daysgrounded/, which means you need to modify __init__.py to add it to sys.path:

import sys
import os.path
sys.path.insert(1, os.path.dirname(__file__))

If you want to be able to do from daysgrounded import cli, sys.path should be the directory above daysgrounded/, which means you need to modify __main__.py to add it to sys.path:

import sys
import os.path
sys.path.insert(1, os.path.dirname(sys.path[0]))
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top