Import python module over the internet/multiple protocols or dynamically create module

梦想的初衷 提交于 2019-12-18 16:50:38

问题


Is it possible to import a Python module from over the internet using the http(s), ftp, smb or any other protocol? If so, how? If not, why?

I guess it's about making Python use more the one protocol(reading the filesystem) and enabling it to use others as well. Yes I agree it would be many folds slower, but some optimization and larger future bandwidths would certainly balance it out.

E.g.:

import site

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

import sqlalchemy
import sqlalchemy.engine

回答1:


In principle, yes, but all of the tools built-in which kinda support this go through the filesystem.

To do this, you're going to have to load the source from wherever, compile it with compile, and exec it with the __dict__ of a new module. See below.

I have left the actually grabbing text from the internet, and parsing uris etc as an exercise for the reader (for beginners: I suggest using requests)

In pep 302 terms, this would be the implementation behind a loader.load_module function (the parameters are different). See that document for details on how to integrate this with the import statement.

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)

At this point newmodule is already a module object in scope, so you don't need to import it or anything.

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

Ideone here: http://ideone.com/dXGziO

Tested with python 2, should work with python 3 (textually compatible print used;function-like exec syntax used).




回答2:


Another version,

I like this answer. when applied it, i simplified it a bit - similar to the look and feel of javascript includes over HTTP.

This is the result:

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

Usage:

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')
  • Tip - place the import_cdn function in a common library, this way you could re-use this small function
  • Bear in mind It will fail when no connectivity to that file over http



回答3:


This seems to be a use case for a self-written import hook. Look up in PEP 302 how exactly they work.

Essentially, you'll have to provide a finder object which, in turn, provides a loader object. I don't understand the process at the very first glance (otherwise I'd be more explicit), but the PEP contains all needed details for implementing the stuff.




回答4:


Take a look at: [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] I use it to import code from my github for development of projects elsewhere.

Although this would be useful for game developers, or web-application designers, and updating your code-base wouldn't take long, even to setup or teardown.




回答5:


As glglgl's has it this import hook has been implemented for Python2 and Python3 in a module called httpimport. It uses a custom finder/loader object to locate resources using HTTP/S.

Additionally, the import_cdn function in Jossef Harush's answer is almost identically implemented in httpimport's github_repo, and bitbucket_repo functions.

@Marcin's answer contains a good portion of the code of the httpimport's loader class.



来源:https://stackoverflow.com/questions/18747043/import-python-module-over-the-internet-multiple-protocols-or-dynamically-create

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!