如何在mod_python中打开并传输文件?
我刚接触mod_python和Apache,现在在处理GET请求后返回文件给用户时遇到了麻烦。我现在的设置非常简单,原本希望能直接打开文件并把它写入响应中:
from mod_python import apache
def handler(req):
req.content_type = 'application/octet-stream'
fIn = open('response.bin', 'rb')
req.write(fIn.read())
fIn.close()
return apache.OK
但是,当我使用open()时却出现错误,提示文件不存在(尽管我检查了好几遍,确认文件是存在的)。无论是用相对路径还是绝对路径都会出现这个问题。
我有两个问题:
- 为什么open()找不到正确的文件?
- 从文件系统返回文件的最佳方法是什么?(我问这个是想确认我没有错过更好的方法来使用mod_python返回文件。)
谢谢
编辑:在找到这个讨论串后: http://www.programmingforums.org/thread12384.html,我发现如果我把文件移动到家目录以外的其他目录,open()就能正常工作(我之前是从/home/myname/httpdocs中别名,但如果使用/data就可以)。你知道为什么这样可以吗?
编辑2:这是我调试错误的一部分,按要求提供:
MOD_PYTHON ERROR
ProcessId: 13642
Interpreter: '127.0.1.1'
ServerName: '127.0.1.1'
DocumentRoot: '/var/www'
URI: '/test/mptest.py'
Location: None
Directory: '/home/myname/httpdocs/'
Filename: '/home/myname/httpdocs/mptest.py'
PathInfo: ''
Phase: 'PythonHandler'
Handler: 'mptest'
Traceback (most recent call last):
File "/usr/lib/python2.5/site-packages/mod_python/importer.py", line 1537, in HandlerDispatch
default=default_handler, arg=req, silent=hlist.silent)
File "/usr/lib/python2.5/site-packages/mod_python/importer.py", line 1229, in _process_target
result = _execute_target(config, req, object, arg)
File "/usr/lib/python2.5/site-packages/mod_python/importer.py", line 1128, in _execute_target
result = object(arg)
File "/home/myname/httpdocs/mptest.py", line 13, in handler
fIn = open('/home/myname/httpdocs/files/response.bin', 'rb')
IOError: [Errno 2] No such file or directory: '/home/myname/httpdocs/files/response.bin'
2 个回答
你能把你遇到的错误信息贴出来吗?
这很可能是权限错误(如果你尝试使用文件的完整路径)。记住,脚本是以运行网页服务器的用户身份来执行的——所以你访问文件时通常是以“www-data”或“nobody”的身份。
也检查一下文件夹 /home/myname/httpdocs/files/
的权限。这个文件夹应该对 www-data
用户有 +x
权限:
$ mkdir blah
$ echo works > blah/response.bin
$ chmod 000 blah/
$ cat blah/response.bin
cat: blah/response.bin: Permission denied
$ chmod +x blah/
$ cat blah/response.bin
works
你可以通过以下方式排除 Apache 或你的脚本的问题:
you:~$ sudo su - www-data
www-data:~$ file /home/myname/httpdocs/files/response.bin
(su 命令可能不管用,这取决于你使用的操作系统或发行版,比如 OS X 不允许你以它的 www
用户身份登录)
除了文件权限,为什么脚本还依赖于你主文件夹里的一个文件呢?能不能把 response.bin
移到和你的 Python 脚本同一个文件夹里?或者干脆放到数据库里?(也许用 SQLite?这可能不必要或过于复杂,具体要看 response.bin
里的内容以及它变化的频率)
要调试这种问题,你需要从正在运行的mod_python实例中收集所有信息。
别再反复“检查它是否存在”了。有些假设是不正确的。
可以尝试这样做来获取一些调试信息。
def handler(req):
req.content_type = 'text/plain'
req.write(os.environ)
req.write(os.getcwd())
# etc.
return apache.OK
补充说明
现在你对重要的内容有了一些了解。在这种情况下,可能是权限问题——你需要使用os.filestat来确认一下。Apache以几乎没有可用权限的用户身份运行mod_python。Apache也不喜欢链接,但这不应该影响mod_python。如果你的文件没有“所有人可读”权限,并且不在正确的目录下,你就会遇到问题。
你可能想考虑切换到mod_wsgi。