【问题标题】:Import python module over the internet/multiple protocols or dynamically create module通过互联网/多种协议导入 python 模块或动态创建模块
【发布时间】:2013-09-15 19:45:27
【问题描述】:

是否可以使用http(s)、ftpsmb 或任何其他协议从 Internet 上 import 一个 Python 模块?如果是这样,怎么做?如果不是,为什么?

我想这是为了让 Python 更多地使用一种协议(读取文件系统)并使其也能够使用其他协议。是的,我同意它会慢很多倍,但一些优化和更大的未来带宽肯定会平衡它。

例如:

import site

site.addsitedir("https://bitbucket.org/zzzeek/sqlalchemy/src/e8167548429b9d4937caaa09740ffe9bdab1ef61/lib")

import sqlalchemy
import sqlalchemy.engine

【问题讨论】:

  • 我想您可以将 URI 添加到 sys.path,但我认为您需要将其安装到本地安装点。我还没有听说过通过 HTTP 进行导入,虽然我对这个概念没有什么经验
  • 可以将.py文件下载到任意目录,然后导入。
  • @7stud duh。我在这里要强调的一点是,无论文件是在目录中还是在 Internet 上,它最终都会在内存中结束,所以为什么要下载然后导入它的额外物流,当唯一的区别时,表面上看, 是“协议”。
  • @inspectorG4dget 什么是上述 URL 的绝对 URI,因为上面的代码不起作用。安装是一个明显的解决方案,但考虑到多个来源,它不会那么便携和实用。想象一下,不必在本地安装 3rd 方包,只需通过 Internet 导入它们!
  • 值得指出的是,JavaScript 在浏览器中已经这样做了几十年,而由 Node.js 的原始创建者制作的 Javascript 运行时 Deno 使用 ES6+ importsyntax 透明地复制了这种行为:import { someExportedProperty } from 'https://any.website'。 Deno 会按照您的描述进行操作:它只是将远程依赖项下载到预先确定的永久缓存中(您可以将其设置为本地目录),然后执行主脚本。

标签: python network-protocols python-import python-exec


【解决方案1】:

正如glglgl 所说,这个导入钩子已经在一个名为httpimport 的模块中为Python2 和Python3 实现。 它使用自定义 finder/loader 对象来使用 HTTP/S 定位资源。

此外,Jossef Harush 的答案中的import_cdn 函数在httpimportgithub_repobitbucket_repo 函数中几乎完全相同。

@Marcin 的回答包含httpimport 的加载器类的大部分代码。

【讨论】:

    【解决方案2】:

    另一个版本,

    我喜欢this 的回答。应用它时,我稍微简化了一点 - 类似于 javascript 的外观和感觉,包括 HTTP

    这是结果:

    import os
    import imp
    import requests
    
    def import_cdn(uri, name=None):
        if not name:
            name = os.path.basename(uri).lower().rstrip('.py')
    
        r = requests.get(uri)
        r.raise_for_status()
    
        codeobj = compile(r.content, uri, 'exec')
        module = imp.new_module(name)
        exec (codeobj, module.__dict__)
        return module
    

    用法:

    redisdl = import_cdn("https://raw.githubusercontent.com/p/redis-dump-load/master/redisdl.py")
    
    # Regular usage of the dynamic included library
    json_text = redisdl.dumps(host='127.0.0.1')
    
    • 提示 - 将import_cdn 函数放在一个通用库中,这样您就可以重复使用这个小函数
    • 请记住,它会在没有通过 http 连接到该文件时失败

    【讨论】:

    • 我不认为这是一种简化 - 你只是将检索与模块加载代码结合起来。
    • imp 自 3.4 版起已弃用。对于较新版本的import impimport typesimp.new_module(name)types.ModuleType(name)
    【解决方案3】:

    这似乎是一个自写导入钩子的用例。在PEP 302 中查找它们的工作原理。

    本质上,您必须提供一个查找器对象,而该查找器对象又提供一个加载器对象。乍一看我不明白这个过程(否则我会更明确),但 PEP 包含实现这些东西所需的所有细节。

    【讨论】:

    • 这很简单。我认为最棘手的是我的回答所涉及的问题;他们在那里有一个例子,涵盖了类似的领域(尽管它更复杂)。
    【解决方案4】:

    原则上,是的,但是所有支持这一点的内置工具都通过文件系统。

    为此,您将不得不从任何地方加载源代码,使用compile 编译它,并使用新模块的__dict__ 编译它exec。见下文。

    我已经从互联网上留下了实际抓取的文本,并解析了 uris 等作为读者的练习(对于初学者:我建议使用requests

    pep 302 术语中,这将是loader.load_module 函数背后的实现(参数不同)。有关如何将其与 import 语句集成的详细信息,请参阅该文档。

    import imp
    modulesource = 'a=1;b=2' #load from internet or wherever
    def makemodule(modulesource,sourcestr='http://some/url/or/whatever',modname=None):
        #if loading from the internet, you'd probably want to parse the uri, 
        # and use the last part as the modulename. It'll come up in tracebacks
        # and the like.
        if not modname: modname = 'newmodulename'
        #must be exec mode
        # every module needs a source to be identified, can be any value
        # but if loading from the internet, you'd use the URI
        codeobj = compile(modulesource, sourcestr, 'exec')
        newmodule = imp.new_module(modname)
        exec(codeobj,newmodule.__dict__)
        return newmodule
    newmodule = makemodule(modulesource)
    print(newmodule.a)
    

    此时newmodule 已经是作用域中的模块对象,因此您不需要导入它或其他任何东西。

    modulesource = '''
    a = 'foo'
    def myfun(astr):
        return a + astr
    '''
    newmod = makemodule(modulesource)
    print(newmod.myfun('bat'))
    

    Ideone 在这里:http://ideone.com/dXGziO

    使用 python 2 测试,应该可以使用 python 3(使用文本兼容的打印;使用类似函数的 exec 语法)。

    【讨论】:

      猜你喜欢
      • 2011-04-17
      • 1970-01-01
      • 1970-01-01
      • 2021-10-14
      • 2022-11-24
      • 1970-01-01
      • 1970-01-01
      • 2015-10-17
      • 2013-02-21
      相关资源
      最近更新 更多