如何在IIS for Python2.7上正确安装isapi wsgi?

2024-09-27 21:31:20 发布

您现在位置:Python中文网/ 问答频道 /正文

我已经把Python作为CGI应用程序安装在windows7上的IIS上。这很简单,但是为了更好的灵活性,我想使用WSGI工具。在

我下载了isapi_wsgi的存档文件,解压缩后,按照the instructions运行安装,如下所示:

\python27\python.exe setup.py install

此操作成功:

enter image description here

然后我编写了一个.py模块,其中包含wsgi胶水,并尝试安装它。失败的原因如下:

enter image description here

这是一个COM名字对象错误,我知道IIS6兼容的管理工具是基于COM名字对象的,这提醒我IIS6兼容管理工具的isapi_wsgi有一个先决条件。我运行了\windows\system32\OptionalFeatures.exe并安装了它,然后重新运行了.py模块并正确安装了它。在

^{pr2}$

好吧,太好了。现在当我查看当前目录时,我看到一个名为_app1的新DLL_wsgi.dll,当我在IIS管理器中查看时,我可以看到一个新的iisvdir,以及该vdir中“*”的脚本映射,该脚本映射到_app1_wsgi.DLL. 一切都好。但是!向http://localhost/wsgi发出请求会产生500个错误。在

通过一些尝试和错误,我发现定义我的处理程序的.py模块必须位于site packages目录中。我对此感到非常惊讶。在

我能避免吗?我可以简单地将.py模块放在与生成的.dll文件相同的目录中吗?或者,我是否需要将所有python逻辑部署到站点包中,以便从WSGI机制运行它?在


Tags: 模块文件对象pycomwsgi错误iis
2条回答

把这个放在你的纸条上:

导入站点 site.addsitedir('path/to/your/site packages')

你遇到的同样的问题,用这两条线解决了

答案是:

  • 问题中描述的isapi wsgi的安装是正确的。

  • 基本样板应用程序副本正如isapi_wsgi附带的示例代码所示,web应用程序的python类需要位于site packages目录中。

  • 可以允许python源模块与生成的*.dll文件位于同一目录中,但它需要在*wsgi.py文件。

  • 在Windows上运行python进行开发的更好方法是下载googleappengine并使用内置的专用http服务器。gaesdk附带的框架处理重新加载,并允许将.py模块放在特定的目录中。


如果您不想下载并安装gaesdk,那么您可以尝试以下方法。使用这段代码,当请求到达isapi_wsgi时,处理程序会在主目录中查找py模块,并加载它。如果模块已经加载,它会检查文件“last modified time”,如果上次修改时间晚于上次加载的时间,则会重新加载模块。它适用于简单的情况,但我认为当存在嵌套的模块依赖关系时,它将变得脆弱。在

import sys
import os
import win32file
from win32con import *

# dictionary of [mtime, module] tuple;  uses file path as key
loadedPages = {}

def request_handler(env, start_response):
    '''Demo app from wsgiref'''
    cr = lambda s='': s + '\n'
    if hasattr(sys, "isapidllhandle"):
        h = None
        # get the path of the ISAPI Extension DLL
        hDll = getattr(sys, "isapidllhandle", None)
        import win32api
        dllName = win32api.GetModuleFileName(hDll)
        p1 = repr(dllName).split('?\\\\')
        p2 = p1[1].split('\\\\')
        sep = '\\'
        homedir = sep.join(p2[:-1])

        # the name of the Python module is in the PATH_INFO
        moduleToImport = env['PATH_INFO'].split('/')[1]

        pyFile = homedir + sep + moduleToImport + '.py'

        fd = None
        try:
            fd = win32file.CreateFile(pyFile, GENERIC_READ, FILE_SHARE_DELETE, None, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)
        except Exception as exc1:
            fd = None

        if fd is not None:
            # file exists, get mtime
            fd.close()
            mt = os.path.getmtime(pyFile)
        else:
            mt = None


        if mt is not None:
            h = None
            if not pyFile in loadedPages:
                # need a new import
                if homedir not in sys.path:
                    sys.path.insert(0, homedir)

                h = __import__(moduleToImport, globals(), locals(), [])
                # remember
                loadedPages[pyFile] = [mt, h]
            else:
                # retrieve handle to module
                h = loadedPages[pyFile][1]
                if mt != loadedPages[pyFile][0]:
                    # need to reload the page
                    reload(h)
                    loadedPages[pyFile][0] = mt

            if h is not None:
                if 'handler' in h.__dict__:
                    for x in h.handler(env, start_response):
                        yield x
                else:
                    start_response("400 Bad Request", [('Content-Type', 'text/html')])
            else:
                start_response("404 Not Found", [('Content-Type', 'text/html')])
                yield cr()
                yield cr("<html><head><title>Module not found</title>" \
                             "</head><body>")
                yield cr("<h3>404 Not Found</h3>")
                yield cr("<h3>No handle</h3></body></html>")

        else:
            start_response("404 Not Found", [('Content-Type', 'text/html')])
            yield cr()
            yield cr("<html><head><title>Module not found</title>" \
                 "</head><body>")
            yield cr("<h3>404 Not Found</h3>")
            yield cr("<h3>That module (" + moduleToImport + ") was not found.</h3></body></html>")


    else:
        start_response("500 Internal Server Error", [('Content-Type', 'text/html')])
        yield cr()
        yield cr("<html><head><title>Server Error</title>" \
                 "</head><body><h1>Server Error - No ISAPI Found</h1></body></html>")


# def test(environ, start_response):
#     '''Simple app as per PEP 333'''
#     status = '200 OK'
#     start_response(status, [('Content-type', 'text/plain')])
#     return ['Hello world from isapi!']


import isapi_wsgi
# The entry point(s) for the ISAPI extension.
def __ExtensionFactory__():
    return isapi_wsgi.ISAPISimpleHandler(request_handler)


def PostInstall(params, options):
    print "The Extension has been installed"


# Handler for our custom 'status' argument.
def status_handler(options, log, arg):
    "Query the status of the ISAPI?"
    print "Everything seems to be fine..."


if __name__=='__main__':
    # This logic gets invoked when the script is run from the command-line.
    # In that case, it installs this module as an ISAPI.

    #
    # The API provided by isapi_wsgi for this is a bit confusing.  There
    # is an ISAPIParameters object. Within that object there is a
    # VirtualDirs property, which itself is a list of
    # VirtualDirParameters objects, one per vdir.  Each vdir has a set
    # of scriptmaps, usually this set of script maps will be a wildcard
    # (*) so that all URLs in the vdir will be served through the ISAPI.
    #
    # To configure a single vdir to serve Python scripts through an
    # ISAPI, create a scriptmap, and stuff it into the
    # VirtualDirParameters object. Specify the vdir path and other
    # things in the VirtualDirParameters object.  Stuff that vdp object
    # into a sequence and set it into the ISAPIParameters thing, then
    # call the vaguely named "HandleCommandLine" function, passing that
    # ISAPIParameters thing.
    #
    # Clear as mud?
    #
    # Seriously, this thing could be so much simpler, if it had
    # reasonable defaults and a reasonable model, but I guess it will
    # work as is.

    from isapi.install import *

    # Setup the virtual directories -
    # To serve from root, set Name="/"
    sm = [ ScriptMapParams(Extension="*", Flags=0) ]
    vdp = VirtualDirParameters(Name="wsgi", # name of vdir/IIS app
                              Description = "ISAPI-WSGI Demo",
                              ScriptMaps = sm,
                              ScriptMapUpdate = "replace"
                              )

    params = ISAPIParameters(PostInstall = PostInstall)
    params.VirtualDirs = [vdp]
    cah = {"status": status_handler}

    # from isapi.install, part of pywin32
    HandleCommandLine(params, custom_arg_handlers = cah)

使用此模型,请求http://foo/wsgi/bar将尝试加载棒.py从带有WSGI.dll文件的主目录。如果棒.py找不到,你得到了404。如果棒.py自上次运行后已更新,它将重新加载。如果杆不能装,你得500分。在

在棒.py必须公开导出名为handler的方法。那个方法一定是一个生成器。是这样的:

^{pr2}$

但正如我所说,我认为GAE可能是使用Windows开发Python web应用程序的更好方法。在

相关问题 更多 >

    热门问题