Python导入MySQLdb,Apache内部服务器错误

3 投票
3 回答
5090 浏览
提问于 2025-04-15 19:04

我遇到了和“.cgi与网络服务器的问题”中描述的类似的问题,虽然我已经检查并测试了之前建议的解决方案,但还是没有成功。

我在Mac OS X 10.5.8上运行同样的程序,使用的是Apache 2.2.13和Python 2.6.4。我可以在Python的命令行和终端中成功运行代码,但当我尝试在“http://localhost/cgi-bin/test.cgi”上运行时,出现了<type 'exceptions.ImportError'>: No module named MySQLdb的错误。如果我把import MySQLdb这一行注释掉,代码就能成功运行。

#!/usr/bin/env python
import cgitb
cgitb.enable() 
import MySQLdb

print "Content-Type: text/html"
print
print "<html><head><title>Books</title></head>"
print "<body>"
print "<h1>Books</h1>"
print "<ul>"

connection = MySQLdb.connect(user='me', passwd='letmein', db='my_db')
cursor = connection.cursor()
cursor.execute("SELECT name FROM books ORDER BY pub_date DESC LIMIT 10")

for row in cursor.fetchall():
    print "<li>%s</li>" % row[0]

print "</ul>"
print "</body></html>"

connection.close()

[编辑] 根据第一个回答:

如果我按照要求修改test.cgi并从终端命令行运行,MySQLdb的目录会显示在sys.path中。然而,当我通过网络服务器运行时,还是会出现同样的错误。如果我在test.cgi中注释掉import MySQLdb并使用新的循环,页面就打不开了。

我该如何设置Apache的PYTHONPATH?在Python命令行中,我尝试了:

import MySQLdb
import os
print os.path.dirname(MySQLdb.__file__)

然后,根据其他帖子,我尝试在原始的test.cgi中添加结果路径:

import sys
sys.path.append('/Library/Frameworks/Python.framework/Versions/6.0.0/lib/python2.6/site-packages/MySQL_python-1.2.3c1-py2.6-macosx-10.5-i386.egg/')

但这还是出现了同样的错误。


[编辑]

不幸的是,这两种解决方案都没有奏效。将路径添加到sys.path中还是出现了之前的错误。硬编码Python二进制文件的路径#!/Library/Frameworks/Python.framework/Versions/Current/bin/python则产生了一个较长的错误,部分内容如下:

A problem occurred in a Python script. Here is the sequence of function calls leading up to the error, in the order they occurred.

 /Library/WebServer/CGI-Executables/test.cgi in ()
   15 #sys.path.append('/Library/Frameworks/Python.framework/Versions/6.0.0/lib/python2.6/site-packages/')
   16 
   17 import MySQLdb
   18 #import _mysql
   19 
MySQLdb undefined
 /Library/WebServer/CGI-Executables/build/bdist.macosx-10.5-i386/egg/MySQLdb/__init__.py in ()
 /Library/WebServer/CGI-Executables/build/bdist.macosx-10.5-i386/egg/_mysql.py in ()
 /Library/WebServer/CGI-Executables/build/bdist.macosx-10.5-i386/egg/_mysql.py in __bootstrap__()
 /Library/Frameworks/Python.framework/Versions/6.0.0/lib/python2.6/site-packages/pkg_resources.py in resource_filename(self=<pkg_resources.ResourceManager instance at 0x3c8a80>, package_or_requirement='_mysql', resource_name='_mysql.so')
  848         """Return a true filesystem path for specified resource"""
  849         return get_provider(package_or_requirement).get_resource_filename(
  850             self, resource_name
  851         )
  852 
self = <pkg_resources.ResourceManager instance at 0x3c8a80>, resource_name = '_mysql.so'

...

<class 'pkg_resources.ExtractionError'>: Can't extract file(s) to egg cache The following error occurred while trying to extract file(s) to the Python egg cache: [Errno 13] Permission denied: '/Library/WebServer/.python-eggs' The Python egg cache directory is currently set to: /Library/WebServer/.python-eggs Perhaps your account does not have write access to this directory? You can change the cache directory by setting the PYTHON_EGG_CACHE environment variable to point to an accessible directory. 
      args = ("Can't extract file(s) to egg cache\n\nThe followin...nt\nvariable to point to an accessible directory.\n",) 
      cache_path = '/Library/WebServer/.python-eggs' 
      manager = <pkg_resources.ResourceManager instance at 0x3c8a80> 
      message = "Can't extract file(s) to egg cache\n\nThe followin...nt\nvariable to point to an accessible directory.\n" 
      original_error = OSError(13, 'Permission denied')

这个错误似乎暗示可能与设置PYTHON_EGG_CACHE和/或权限有关……

3 个回答

0

为了测试Apache使用的是哪个版本的Python,我添加了以下代码:

import sys
version = sys.version
path = sys.path

...

print "<h1>%s</h1>" % version                                                                  
print "<h1>%s</h1>" % path

这段代码显示Apache确实在使用厂家预装的Python 2.5.1,而不是Python 2.6.4和相关的MySQLdb模块。因此,我在原来的test.cgi中添加了以下代码,解决了这个问题:

import os
os.environ['PYTHON_EGG_CACHE'] = '/tmp'
import sys
sys.path.append('/Library/Frameworks/Python.framework/Versions/6.0.0/lib/python2.6/site-packages/MySQL_python-1.2.3c1-py2.6-macosx-10.5-i386.egg')

可能还有一种系统性的解决办法,就是修改APACHE的httpd.conf中的PYTHONPATH,但我还没有搞明白怎么做。


这个回答是对问题的一个编辑,问题是Python导入MySQLdb时,Apache内部服务器错误,由提问者bernie发布,遵循CC BY-SA 2.5协议。

1

我也遇到过这个问题,不过经过几个小时的尝试,我终于搞定了。

这是我的情况:我需要在一个Python的cgi文件中使用import MySQLdb,但是失败了,出现了ImportError的错误。

然后我打印出了网页服务器的路径和本地Python的路径,它们是:

网页服务器路径

/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python27.zip
/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7
/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-darwin
/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-mac
/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-mac/lib-scriptpackages
/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python
/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-tk
/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-old
/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-dynload
/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/PyObjC

/Library/Python/2.7/site-packages

还有Python路径:

/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/distribute-0.6.25-py2.7.egg
/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/pydelicious-0.6-py2.7.egg
/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/feedparser-5.1.2-py2.7.egg
/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/googlemaps-1.0.2-py2.7.egg
/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/MySQL_python-1.2.3-py2.7-macosx-10.5-intel.egg
/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/elementtree-1.2.7_20070827_preview-py2.7.egg
/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/oauth2-1.5.170-py2.7.egg
/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/httplib2-0.7.4-py2.7.egg
/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/simplejson-2.1.6-py2.7-macosx-10.5-intel.egg
/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/python_twitter-0.8.3-py2.7.egg
/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/South-0.7.6-py2.7.egg
/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/pyfb-0.4.1-py2.7.egg
/usr/local/lib/wxPython-ansi-2.8.12.1/lib/python2.7/site-packages
/usr/local/lib/wxPython-ansi-2.8.12.1/lib/python2.7/site-packages/wx-2.8-mac-ansi
/Library/Frameworks/Python.framework/Versions/2.7/lib/python27.zip
/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7
/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-darwin
/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-mac
/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-mac/lib-scriptpackages
/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-tk
/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-old
/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-dynload
/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages
/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/PIL
/usr/local/lib/wxPython-ansi-2.8.12.1/lib/python2.7

/Library/Python/2.7/site-packages

这两个路径都是/Library/Python/2.7/site-packages,显然这是用来安装第三方包的路径,但它是空的。

为什么呢?

我可以在本地的Python环境中很好地运行带有额外包的Python脚本,然后我注意到那些包都是安装在

/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/

当我在网页服务器上运行cgi文件时,服务器找不到上面的路径,当然import MySQLdb就失败了。

我做的就是把

/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/"

里的文件复制到

/Library/Python/2.7/site-packages

,这样就成功了。

2

确保Apache使用的Python程序里有MySQLdb这个库在它的PYTHONPATH里。

你可以通过检查正在运行的脚本中MySQLdb的位置来确认这一点:

import os
print os.path.dirname(MySQLdb.__file__)

然后把这个位置和test.cgi里面的sys.path的输出进行对比:

import sys
for p in sys.path: 
    print p + "<br/>"

如果在正常工作的脚本中MySQLdb的目录不在坏掉的脚本的sys.path里,那就是问题所在。

补充:

根据楼主的更新,看来你需要添加到PYTHONPATH里的目录是/Library/Frameworks/Python.framework/Versions/6.0.0/lib/python2.6/site-packages/。你之前用的另一个路径:

/Library/Frameworks/Python.framework/Versions/6.0.0/lib/python2.6/site-packages/MySQL_python-1.2.3c1-py2.6-macosx-10.5-i386.egg/

... 是你安装的.egg文件的位置。我不喜欢.egg安装,因为这会让人困惑,尤其是对刚接触Python的人来说。

另外一个选择是直接在你的test.cgi里写死Python程序的路径,和你从命令行确认的那个路径一致。在你的脚本里,你用的是/usr/bin/env python,这是个好习惯。不过,当你遇到环境和路径的问题时,直接写死Python程序的路径可能会更好,直到你解决这个问题。

在命令行里执行which python,来确定命令行引用的是哪个Python程序:

% which python
/opt/local/bin/python 

我的Python程序的路径是/opt/local/bin/python。所以如果你的也是这个,就把test.cgi里的/usr/bin/env python替换成这个:

#!/opt/local/bin/python
import cgitb
# ... and so on ...

这样做之后,你还收到ImportError吗?如果有,那你就更接近问题的根源了。把/Library/Frameworks/Python.framework/Versions/6.0.0/lib/python2.6/site-packages/添加到sys.path里,可能会解决你的问题,而不需要硬编码Python程序的路径。

撰写回答