Python &引用;导入错误:模块';xxxxxxxx和x27;没有属性';主要'&引用;将项目移植到Heroku时

Python &引用;导入错误:模块';xxxxxxxx和x27;没有属性';主要'&引用;将项目移植到Heroku时,python,heroku,pyramid,Python,Heroku,Pyramid,我正在尝试将Python金字塔应用程序移植到Heroku 我必须承认,我不理解Python应用程序的文件结构,即使在阅读了这篇信息丰富的文章之后,它似乎包含了所有的答案: 我已经把一切都准备好了,这样我就可以把源代码更新推送到Heroku,并尝试进行构建。整个过程正在崩溃,因为明显缺少一个“主”属性。我不知道从哪里开始解决这个问题,因为我不知道“main”是什么,它的结构应该是什么,或者它应该驻留在什么文件中 我已经粘贴了我认为相关的内容,但请告诉我是否遗漏了一些有用的内容 我尝试按照这里的说明

我正在尝试将Python金字塔应用程序移植到Heroku

我必须承认,我不理解Python应用程序的文件结构,即使在阅读了这篇信息丰富的文章之后,它似乎包含了所有的答案:

我已经把一切都准备好了,这样我就可以把源代码更新推送到Heroku,并尝试进行构建。整个过程正在崩溃,因为明显缺少一个“主”属性。我不知道从哪里开始解决这个问题,因为我不知道“main”是什么,它的结构应该是什么,或者它应该驻留在什么文件中

我已经粘贴了我认为相关的内容,但请告诉我是否遗漏了一些有用的内容

我尝试按照这里的说明进行操作:

文件结构:

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'
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 + '\n\n' + 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) 大多数
setup.py
文件都希望从自己的目录中执行。当您运行
python some_folder/setup.py develop
时,您要求的是一段糟糕的时间
pip
为您解决了这个问题,您应该通过执行
pip安装-e一些\u文件夹来切换到它

2) 确保与
setup.py
相同的文件夹中没有
init.py
,因为这可能会混淆依赖
PYTHONPATH
发现代码的
runapp.py
脚本,并且当前文件夹通常位于路径上,这意味着带有
设置的文件夹.py
可以被视为一个包(并且在
\uuuu init\uuuuuuu.py
中找不到
main


要想弄明白这一点,最大的考验就是尝试在失败的环境中运行
python
,然后尝试
import corefinance
,看看你得到了什么。这应该会给你一些线索,说明它为什么不起作用。

问题在于我的文件结构有一个额外的层次。正确的文件不在e根,你真的很接近了
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()