python - 在 python 中启动 SimpleHTTPServer

标签 python module command-line-interface program-entry-point

是否有比复制/过去更好的更优雅/系统/面向 future 的方式来调用 if __name__ == '__main__' 中的所有代码?

我正在将我的 bash 脚本转换为 python。我们经常使用的两个命令是 python -m SimpleHTTPServer YOUR_PORTpython -m http.server YOUR_PORT

在 2.x 中翻译这个是相当干净的。

SimpleHTTPServer main :

if __name__ == '__main__':
    test()

我模拟主要的代码:

import SimpleHTTPServer
SimpleHTTPServer.test()

在 3.x 中翻译这个不干净。

http.server main :

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('--cgi', action='store_true',
                       help='Run as CGI Server')
    parser.add_argument('--bind', '-b', default='', metavar='ADDRESS',
                        help='Specify alternate bind address '
                             '[default: all interfaces]')
    parser.add_argument('port', action='store',
                        default=8000, type=int,
                        nargs='?',
                        help='Specify alternate port [default: 8000]')
    args = parser.parse_args()
    if args.cgi:
        handler_class = CGIHTTPRequestHandler
    else:
        handler_class = SimpleHTTPRequestHandler
    test(HandlerClass=handler_class, port=args.port, bind=args.bind)

我模拟主要的代码:

import argparse
import http.server
from http.server import CGIHTTPRequestHandler, SimpleHTTPRequestHandler
parser = argparse.ArgumentParser()
parser.add_argument('--cgi', action='store_true',
                   help='Run as CGI Server')
parser.add_argument('--bind', '-b', default='', metavar='ADDRESS',
                    help='Specify alternate bind address '
                         '[default: all interfaces]')
parser.add_argument('port', action='store',
                    default=8000, type=int,
                    nargs='?',
                    help='Specify alternate port [default: 8000]')
args = parser.parse_args()
if args.cgi:
    handler_class = CGIHTTPRequestHandler
else:
    handler_class = SimpleHTTPRequestHandler
http.server.test(HandlerClass=handler_class, port=args.port, bind=args.bind)

最佳答案

这看起来很糟糕,我不确定这是否是最好的方法,但是下面的代码似乎可以毫不费力地启动服务器:

import importlib
exec(compile(importlib.util.find_spec('http.server').loader.get_source(
    'http.server'), 'server.py', 'exec'), dict(__name__='__main__'))

更新 1: 启动 http.server 模块的下一个想法可能不会好多少,但它利用了 http.server直接模块,而不必处理 importlib 模块。

import http.server
exec(compile(http.server.__loader__.get_source(http.server.__name__),
             http.server.__file__, 'exec'), dict(__name__='__main__'))

当然,这可能只是意味着最好创建一个实用函数来处理在我们想要运行它们的任何上下文中执行模块。

import sys

nvl = lambda value, other: other if value is None else value

def exec_module(module, globals=None, locals=None):
    frame = sys._getframe(1)
    globals = nvl(globals, {})
    globals.update(frame.f_globals)
    locals = nvl(locals, {})
    locals.update(frame.f_locals)
    exec(compile(module.__loader__.get_source(module.__name__),
                 module.__file__, 'exec'), globals, locals)

# this is how you would use the code up above

import http.server

exec_module(http.server, dict(__name__='__main__'))

更新 2: exec_module 函数可能更像下面这样,但由于某种原因没有引起我的注意,它似乎不起作用正如预期的那样:

def exec_module(module, globals=None, locals=None):
    frame = sys._getframe(1)

    exec_globals = nvl(globals, {})
    copy_globals = exec_globals.copy()
    exec_globals.update(frame.f_globals)
    exec_globals.update(copy_globals)

    exec_locals = nvl(locals, {})
    copy_locals = exec_locals.copy()
    exec_locals.update(frame.f_locals)
    exec_locals.update(copy_locals)

    exec(compile(module.__loader__.get_source(module.__name__),
                 module.__file__, 'exec'), exec_globals, exec_locals)

这些变化考虑到了两件事。首先,保留对传入的全局变量和局部变量的引用,以防调用者想在函数运行后检查它们的状态。其次,来自调用者的全局变量和局部变量不能覆盖传入的全局变量和局部变量中已经设置的任何值。

关于python - 在 python 中启动 SimpleHTTPServer,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29434802/

相关文章:

python - 快速索引

linux - DBD::Oracle 安装导致错误

ruby-on-rails - 如何在 Ruby 中封装包含的模块方法?

php - PHP 7.1+ Windows readline扩展并非所有功能都存在

python - 使用 Freebase API 时如何从 mqlread() 获取光标?

python - Django 命令 : How to insert newline in the help text?

python - 使用 ECB 模式加密解密字节时出现问题

php - Zend 框架 : Forms in modules

python - 如何为点击处理的参数列表指定默认值?

ruby - 如何使用 Trollop 制作用于命令行解析的 Ruby 脚本?