«ImportError: модуль ‘xxxxxxxx’ не имеет атрибута ‘main'» при переносе проекта на Heroku

#python #heroku #pyramid

#python #heroku #пирамида

Вопрос:

Я пытаюсь перенести приложение Python pyramid на Heroku.

Я должен признать, что я не понимаю файловую структуру приложения на Python, даже после прочтения этой очень информативной темы, которая, похоже, содержит все ответы: https://what .thedailywtf.com/topic/18922/python-project-structure/27

У меня все настроено, так что я могу отправлять обновления исходного кода в Heroku и пытаться получить сборку. Весь процесс завершается сбоем из-за, по-видимому, отсутствующего атрибута ‘main’. Я не знаю, с чего начать с этой проблемы, поскольку я не знаю, что такое «main», какой должна быть его структура или в каком файле он должен находиться.

Я вставил то, что, по моему мнению, является соответствующими битами ниже, но, пожалуйста, скажите мне, не упустил ли я что-то, что могло бы быть полезным.

Я пытаюсь следовать инструкциям здесь: http://docs.pylonsproject.org/projects/pyramid_cookbook/en/latest/deployment/heroku.html

Структура файла:

 Procfile
run
runapp.py
wsgi.py
--->/corefinance/
----setup.py
----production.ini
------->/corefinance/
--------__init__.py
  

Ошибки сборки Heroku:

 2016-10-10T04:44:45.496214 00:00 app[web.1]: 
2016-10-10T04:44:45.496215 00:00 app[web.1]: Using /app/.heroku/python/lib/python3.5/site-packages
2016-10-10T04:44:45.497067 00:00 app[web.1]: Searching for zope.deprecation==4.1.1
2016-10-10T04:44:45.497245 00:00 app[web.1]: Best match: zope.deprecation 4.1.1
2016-10-10T04:44:45.497356 00:00 app[web.1]: Adding zope.deprecation 4.1.1 to easy-install.pth file
2016-10-10T04:44:45.497742 00:00 app[web.1]: 
2016-10-10T04:44:45.497745 00:00 app[web.1]: Using /app/.heroku/python/lib/python3.5/site-packages
2016-10-10T04:44:45.498530 00:00 app[web.1]: Searching for Mako==1.0.0
2016-10-10T04:44:45.498709 00:00 app[web.1]: Best match: Mako 1.0.0
2016-10-10T04:44:45.498818 00:00 app[web.1]: Adding Mako 1.0.0 to easy-install.pth file
2016-10-10T04:44:45.503267 00:00 app[web.1]: Installing mako-render script to /app/.heroku/python/bin
2016-10-10T04:44:45.503522 00:00 app[web.1]: 
2016-10-10T04:44:45.503524 00:00 app[web.1]: Using /app/.heroku/python/lib/python3.5/site-packages
2016-10-10T04:44:45.503725 00:00 app[web.1]: Finished processing dependencies for corefinance==0.0
2016-10-10T04:44:46.082134 00:00 app[web.1]: Traceback (most recent call last):
2016-10-10T04:44:46.082145 00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.5/site-packages/setuptools-25.2.0-py3.5.egg/pkg_resources/__init__.py", line 2238, in resolve
2016-10-10T04:44:46.082291 00:00 app[web.1]: AttributeError: module 'corefinance' has no attribute 'main'
2016-10-10T04:44:46.082295 00:00 app[web.1]: 
2016-10-10T04:44:46.082296 00:00 app[web.1]: During handling of the above exception, another exception occurred:
2016-10-10T04:44:46.082297 00:00 app[web.1]: 
2016-10-10T04:44:46.082299 00:00 app[web.1]: Traceback (most recent call last):
2016-10-10T04:44:46.082334 00:00 app[web.1]:   File "runapp.py", line 8, in <module>
2016-10-10T04:44:46.082511 00:00 app[web.1]:     app = loadapp('config:production.ini', relative_to='./corefinance/')
2016-10-10T04:44:46.082519 00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.5/site-packages/paste/deploy/loadwsgi.py", line 247, in loadapp
2016-10-10T04:44:46.082666 00:00 app[web.1]:     return loadobj(APP, uri, name=name, **kw)
2016-10-10T04:44:46.082668 00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.5/site-packages/paste/deploy/loadwsgi.py", line 271, in loadobj
2016-10-10T04:44:46.082894 00:00 app[web.1]:     global_conf=global_conf)
2016-10-10T04:44:46.082898 00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.5/site-packages/paste/deploy/loadwsgi.py", line 296, in loadcontext
2016-10-10T04:44:46.083142 00:00 app[web.1]:     global_conf=global_conf)
2016-10-10T04:44:46.083165 00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.5/site-packages/paste/deploy/loadwsgi.py", line 320, in _loadconfig
2016-10-10T04:44:46.083511 00:00 app[web.1]:     return loader.get_context(object_type, name, global_conf)
2016-10-10T04:44:46.083514 00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.5/site-packages/paste/deploy/loadwsgi.py", line 454, in get_context
2016-10-10T04:44:46.083857 00:00 app[web.1]:     section)
2016-10-10T04:44:46.083862 00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.5/site-packages/paste/deploy/loadwsgi.py", line 476, in _context_from_use
2016-10-10T04:44:46.084217 00:00 app[web.1]:     object_type, name=use, global_conf=global_conf)
2016-10-10T04:44:46.084221 00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.5/site-packages/paste/deploy/loadwsgi.py", line 406, in get_context
2016-10-10T04:44:46.084536 00:00 app[web.1]:     global_conf=global_conf)
2016-10-10T04:44:46.084539 00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.5/site-packages/paste/deploy/loadwsgi.py", line 296, in loadcontext
2016-10-10T04:44:46.084822 00:00 app[web.1]:     global_conf=global_conf)
2016-10-10T04:44:46.084826 00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.5/site-packages/paste/deploy/loadwsgi.py", line 328, in _loadegg
2016-10-10T04:44:46.085119 00:00 app[web.1]:     return loader.get_context(object_type, name, global_conf)
2016-10-10T04:44:46.085123 00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.5/site-packages/paste/deploy/loadwsgi.py", line 620, in get_context
2016-10-10T04:44:46.085560 00:00 app[web.1]:     object_type, name=name)
2016-10-10T04:44:46.085561 00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.5/site-packages/paste/deploy/loadwsgi.py", line 646, in find_egg_entry_point
2016-10-10T04:44:46.086013 00:00 app[web.1]:     possible.append((entry.load(), protocol, entry.name))
2016-10-10T04:44:46.086015 00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.5/site-packages/setuptools-25.2.0-py3.5.egg/pkg_resources/__init__.py", line 2230, in load
2016-10-10T04:44:46.086217 00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.5/site-packages/setuptools-25.2.0-py3.5.egg/pkg_resources/__init__.py", line 2240, in resolve
2016-10-10T04:44:46.086408 00:00 app[web.1]: ImportError: module 'corefinance' has no attribute 'main'
  

выполнить

 #!/bin/bash
set -e
python ./corefinance/setup.py develop
python runapp.py
  

runapp.py

 import os

from paste.deploy import loadapp
from waitress import serve

if __name__ == "__main__":
    port = int(os.environ.get("PORT", 5000))
    app = loadapp('config:production.ini', relative_to='./corefinance/')

    serve(app, host='0.0.0.0', port=port)
  

./corefinance/setup.py

 import os

from setuptools import setup, find_packages

here = os.path.abspath(os.path.dirname(__file__))
with open(os.path.join(here, 'README.txt')) as f:
    README = f.read()
with open(os.path.join(here, 'CHANGES.txt')) as f:
    CHANGES = f.read()

requires = [
    'setuptools',
    'markupsafe',
    'pyramid',
    'pyramid_chameleon',
    'pyramid_debugtoolbar',
    'pyramid_tm',
    'SQLAlchemy',
    'transaction',
    'zope.sqlalchemy',
    'waitress',
    'docutils',
    'pyramid_exclog',
    'cryptacular',
    'pycrypto',
    'webtest',
    ]


setup(name='corefinance',
      version='0.0',
      description='corefinance',
      long_description=README   'nn'   CHANGES,
      classifiers=[
        "Programming Language :: Python",
        "Framework :: Pyramid",
        "Topic :: Internet :: WWW/HTTP",
        "Topic :: Internet :: WWW/HTTP :: WSGI :: Application",
        ],
      author='',
      author_email='',
      url='',
      keywords='web wsgi bfg pylons pyramid',
      packages=find_packages(),
      include_package_data=True,
      zip_safe=False,
      test_suite='corefinance',
      install_requires=requires,
      entry_points="""
      [paste.app_factory]
      main = corefinance:main
      [console_scripts]
      initialize_corefinance_db = corefinance.scripts.initializedb:main
      """,
      )
  

./corefinance/corefinance/init.py

 from pyramid.config import Configurator
from sqlalchemy import engine_from_config
from configparser import SafeConfigParser

import os

from pyramid.authentication import AuthTktAuthenticationPolicy
from pyramid.authorization import ACLAuthorizationPolicy
from pyramid.session import SignedCookieSessionFactory
from .security import groupfinder

from sqlalchemy import engine_from_config

from corefinance.models.meta import DBSession
from corefinance.models.utilities import RootFactory
from corefinance.models.meta import Base


def main(global_config, **settings):
    """ This function returns a Pyramid WSGI application.
    """ 

    parser = SafeConfigParser()
    db_ini_file = settings['db_ini_file']
    iniloc = os.path.abspath(os.path.join(os.path.dirname( __file__ ), '..', db_ini_file))
    read_list = parser.read(iniloc)
    connstring = parser.get('postgres', 'connstring')
    settings['sqlalchemy.url'] = connstring

    engine = engine_from_config(settings, 'sqlalchemy.')
    DBSession.configure(bind=engine)

    session_factory = SignedCookieSessionFactory(
        settings['session.secret']
        )

    authn_policy = AuthTktAuthenticationPolicy(
        settings['session.secret'], callback=groupfinder, hashalg='sha512')
    authz_policy = ACLAuthorizationPolicy()

    config = Configurator(
        settings=settings,
        root_factory=RootFactory,
        authentication_policy=authn_policy,
        authorization_policy=authz_policy,
        session_factory=session_factory
        )    

    Base.metadata.bind = engine
    config.include('pyramid_chameleon')
    config.include(addroutes)
    config.scan()
    return config.make_wsgi_app()
  

Ответ №1:

Я не думаю, что есть четкая причина, по которой это не работает. Есть несколько вещей, которые вы могли бы улучшить.

1) setup.py Ожидается, что большинство файлов будут выполняться из их собственного каталога. При запуске python some_folder/setup.py develop вы просите о неудачном времени. pip решает это за вас, и вы должны переключиться на него, выполнив pip install -e some_folder .

2) Убедитесь __init.py__ , что в той же папке, что и as, нет an setup.py , что может привести к путанице для вашего runapp.py скрипта, который полагается на PYTHONPATH обнаружение кода, и текущая папка обычно находится на пути, означающем, что папка с вашим setup.py может считаться пакетом (и в ней не main найдено __init__.py .

Большой тест, чтобы разобраться в этом, — это просто попробовать и запустить python в той же среде, которая терпит неудачу import corefinance , и попытаться посмотреть, что у вас получится. Это должно дать вам некоторые подсказки относительно того, почему он не работает.

Комментарии:

1. Проблема заключалась в том, что у меня был дополнительный уровень в файловой структуре. Соответствующие файлы не были в корне. Итак, вы действительно приблизились