通过Internet /多个协议导入python模块或动态创建模块

时间:2013-09-11 16:55:23

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

是否可以使用importhttp),sftp或任何其他协议通过互联网smb使用Python模块?如果是这样,怎么样?如果没有,为什么?

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

E.g:

import site

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

import sqlalchemy
import sqlalchemy.engine

5 个答案:

答案 0 :(得分:4)

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

要执行此操作,您必须从任何地方加载源代码,使用compile进行编译,并使用exec新模块进行__dict__编译。见下文。

我从互联网上留下了实际抓取的文本,并将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语法)。

答案 1 :(得分: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
  • 在没有连接时会失败

答案 2 :(得分:1)

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

基本上,您必须提供一个finder对象,而该对象又提供一个loader对象。我乍一看并不理解这个过程(否则我会更明确),但PEP包含了实现这些内容所需的所有细节。

答案 3 :(得分:0)

看看:[https://github.com/Asmeble/Languages/raw/Documentation-of-5/13/2018-%22What-you-think-is-left-for-indifference-has-yet-to-shape-or-be-shaped%22/Python3.6/URL_import.py] 我用它从我的github导入代码以开发其他地方的项目。

尽管这对游戏开发人员或Web应用程序设计人员很有用,并且更新您的代码库不会花很长时间,甚至无需安装或拆卸。

答案 4 :(得分:0)

正如glglgl一样,此导入挂钩已在名为httpimport的模块中为Python2和Python3实现。 它使用自定义查找程序/加载程序对象通过HTTP / S定位资源。

另外,Jossef Harush的答案中的import_cdn函数在httpimport的{​​{3}}和github_repo函数中几乎完全相同。

@Marcin的答案包含httpimport的加载程序类的大部分代码。