无法导入模块

6

我创建了一个Python Web应用程序,其目录结构如下:

# cd /usr/local/www/myapp

modules
    layout
        __init__.py
        layout.py
packages
public
myapp.wsgi

我已将PYTHONPATH设置为:

/usr/local/www/myapp/modules:/usr/local/www/myapp/packages

在myapp.wsgi中,我试图做以下操作:
import layout

但是我遇到了内部服务器错误,为什么呢?

这是我的 myapp.wsgi 文件(如果我注释掉 import layout 这一行,它就可以正常工作):

import sys
import wsgiref
import layout    
def application(environ, start_response):
        response_status = '200 OK'
        response_body = 'Hello! '
        response_headers = []
        content_type = ('Content-type', 'text-plain')
        content_length = ('Content-Length', str(len(response_body)))
        response_headers.append(content_type)
        response_headers.append(content_length)
        start_response(response_status, response_headers)
        return [response_body]

我收到的完整错误信息如下:

Internal Server Error

The server encountered an internal error or misconfiguration and was unable to complete your request.

Please contact the server administrator, webmaster@example.com and inform them of the time the error occurred, and anything you might have done that may have caused the error.

More information about this error may be available in the server error log.

我的虚拟主机配置:

<VirtualHost *:80>

    ServerName localhost
    ServerAlias localhost
    ServerAdmin webmaster@example.com

    DocumentRoot /usr/local/www/myapp/public

    <Directory /usr/local/www/myapp/public>
    Order allow,deny
    Allow from all
    </Directory>

    WSGIScriptAlias / /usr/local/www/myapp/myapp.wsgi

    <Directory /usr/local/www/myapp>
    Order allow,deny
    Allow from all
    </Directory>

</VirtualHost>

/var/log/httpd-error.log 中的错误:

[Fri Jan 20 15:31:03 2012] [error] [client 192.168.201.123] mod_wsgi (pid=1725): Target WSGI script '/usr/local/www/myapp/myapp.wsgi' cannot be loaded as Python module.
[Fri Jan 20 15:31:03 2012] [error] [client 192.168.201.123] mod_wsgi (pid=1725): Exception occurred processing WSGI script '/usr/local/www/myapp/myapp.wsgi'.
[Fri Jan 20 15:31:03 2012] [error] [client 192.168.201.123] Traceback (most recent call last):
[Fri Jan 20 15:31:03 2012] [error] [client 192.168.201.123]   File "/usr/local/www/myapp/myapp.wsgi", line 3, in <module>
[Fri Jan 20 15:31:03 2012] [error] [client 192.168.201.123]     import layout
[Fri Jan 20 15:31:03 2012] [error] [client 192.168.201.123] ImportError: No module named layout

print sys.path的输出结果:

enter image description here


1
请至少包含您收到的完整和准确的错误消息。 - unwind
@unwind 添加了我在浏览器中收到的错误消息和我的虚拟主机配置。 - Richard Knop
你贴出的错误信息并不是我们要找的——它提示你需要检查服务器错误日志。请寻找 Python 的“Traceback”。另外,我想知道你是否只是错误地指定了导入方式。如果 layout.py 包含所需的代码,则需要执行 import layout.layoutfrom layout import layout - jrennie
@jrennie 我已经从var/log/httpd-error.log中添加了错误信息。我还尝试了导入layout.layout,但是它仍然抛出相同的错误。 - Richard Knop
@RichardKnop:有用的方法是在Web服务器执行脚本时,让脚本打印/记录sys.path。如果“modules”目录不是“sys.path”的一部分,则“import layout”将失败。请注意,“modules”目录不在您的“sys.path”示例中。 - jrennie
显示剩余4条评论
5个回答

8

第一次尝试:

python /usr/local/www/myapp/myapp.wsgi

它是否正确加载?

如果是的话,那么您可能有一些环境变量(在〜/ .bashrc 或类似位置)需要用于应用程序。请尝试:

# to wipe-out extra env
env -i bash
# try again
python /usr/local/www/myapp/myapp.wsgi

请确认您在shell中使用的Python版本与Apache WSGI使用的版本相同。

如果您的 myapp.wsgi 需要任何额外的env才能正确加载,则可以执行以下操作之一:

  • 在apache中设置 python path ,或者
  • 在运行时在myapp.wsgi中设置

要在WSGI代码中设置,请参阅示例代码。

import os, sys
EXTRA_DIR = os.path.realpath(os.path.join(os.path.dirname(__file__), '..', '..'))
if EXTRA_DIR not in sys.path:
    sys.path.append(EXTRA_DIR)

将其放在myapp.wsgi文件的开头。


我尝试过所有的方法,但都没有成功。因为我正在使用FreeBSD,所以"env -i bash"命令并不起作用。 - Richard Knop
python /usr/local/www/myapp/myapp.wsgi 的输出是什么? - Michał Šrajer
1
@RichardKnop:如我在帖子中所述,您需要在Apache配置中使用WSGIPythonPath或在您的wsgi代码中使用sys.path.append()。 - Michał Šrajer
@RichardKnop: 更具体地说,将 WSGIPythonPath /usr/local/www/myapp/modules 添加到您的 Apache 配置中。 - jrennie
这对我有用。在命令行上使用 python directory/wsgi.py 正常执行 wsgi.py,解决了我的问题。看起来很简单。 - Paul Carlton
显示剩余3条评论

1
你的 layout 文件夹中有一个 __init.__py,但它应该是 __init__.py。这里句号位置错误了。我不确定这是你帖子中的错别字还是其他原因造成的,但如果你的文件是这样的话,那么就会导致出现问题。

0
根据http://webpy.org/install#apachemodwsgi,如果在 Apache error.log 文件中出现“ImportError: No module named web”,您可以在导入 web 之前在 code.py 中设置绝对路径。
import sys, os
abspath = os.path.dirname(__file__)
sys.path.append(abspath)
os.chdir(abspath)
import web

这对我来说非常有效。


0

我曾经遇到过类似的问题,这个方法解决了它:

chmod a+x myapp.wsgi

0

模块目录还需要定义一个__init__.py文件作为包。


1
基于所指定的 PYTHONPATHmodules 不是一个包。 - jrennie

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接