Understanding import

Understanding import

import hello
hello.say_hello(
 

 

The first thing we need to understand to do this is how Python’s import mechanism works; in other words, the exact steps Python goes through when it encounters an import statement. If you want all the gory details, the official Python documentation on importing isn’t too bad an explanation of this process, and Fredrik Lundh has an excellent write-up of all the nooks and crannies of Python’s importing mechanism . I highly recommend giving both of those a thorough read at some point, but for now let’s walk through the key points together.

When you have a statement like import hello in a Python program, Python goes through two steps to actually import it:

  1. Locate and, if necessary, initialize the module.
  2. Bind the resulting module object to a name in your current scope.

So when Python sees import hello , it wants to locate and possibly initialize a module named hello , then assign the resulting module object to the name hello in your program’s current scope. If the import statement ocurs at the top of a file, hello will become a module-global name, for example.

The first step — locating and initializing the module — can happen in either of a couple of ways:

  1. If the module hasn’t already been initialized, that needs to happen. For most Python modules, that simply consists of executing the code in the module so that, for example, any classes or functions it contains get defined.
  2. If the module has already been initialized, there will be a module object already in memory for it, and Python can simply grab that object.

Python figures out whether the module has already been initialized by looking at a dictionary named modules which lives inside the built-in module “sys” of the Python standard library; sys.modules has keys corresponding to the import paths of modules which have already been loaded and initialized, and the values are the resulting module objects.

So the actual mechanism is pretty simple: when we say import hello in a Python program, Python goes and looks for the key “hello” in the sys.modules dictionary. If that key exists, Python gets the already-initialized module object out of sys.modules[‘hello’] , and if it doesn’t then Python goes out to your file system and starts looking through the directories on your Python import path for a file or module named hello , which will — if found — be initialized and create an entry in sys.modules . If it isn’t found, Python will raise an ImportError .

One important thing to note here is that if you have a module which can conceivably be imported in multiple different ways — say, because both your project directory and application are directly on your Python path, so that both from myproject.blog.models import Entry and from blog.models import Entry will work — you can end up with a single module getting initialized more than once, and having more than one entry in sys.modules (one for each different way you’ve imported it). Significant sections of Django’s model-loading code exist to work around this and ensure that a given model class only gets initialized once.

Also, note that for module names which contain dots (e.g., import foo.bar ), the mechanism is slightly different: Python looks for an entry in sys.modules which matches up to, but not including, the right-most dot, then looks inside the resulting module object for the final part. So in the statement import foo.bar.baz , Python looks for the entry “foo.bar” in sys.modules , then looks for something named baz inside the resulting module object.

By now you might be wondering whether, since sys.modules is a dictionary, you can just go stick things into it. The answer is that you can: you’re free to do anything to sys.modules that’s legal to do to a Python dictionary, though it’s almost always a bad idea to go messing around with it. But this points the way to how we’re going to make our eventual import statement work: once we’ve constructed the hello module, we can simply stick it into sys.modules and Python will happily let us import it without ever bothering to check if an actual module of that name exists on the file system.

Understanding modules

If you’ve ever tried to access, say, a nonexistent Django setting, you’ve probably seen an error like this:

AttributeError: 'module' object has no attribute 'some_random_name'


And so far I’ve been using the phrase “module object” to refer to Python modules. Both of these give us a clue about how we can build a module on the fly: modules, like everything else in Python, are simply objects, and you can instantiate new module objects just as you can instantiate objects from classes you’ve defined in your applications, assuming you know where to look.

The place to look is another module from Python’s standard library : types , which contains the type objects for many of Python’s built-in types. If you know your way around the types module, you can dynamically build nearly any sort of standard Python object on the fly, even some objects that you can’t normally construct otherwise. In this case the one we’re interested in is types.ModuleType , which we can use to create a brand-new module object at runtime; it works the same as instantiating any other object, and requires at least one argument: the name of the module object to create. You can also optionally pass a second argument which will become the new module’s docstring, so that Python’s built-in help() function will be able to show documentation for it (and other automated documentation parsers will be able to extract its documentation), but we’ll leave that off for this example.

So let’s go ahead and start building our hello module. Pop open a Python interpreter and type in the following:

import types
hello_mod = types ModuleType('hello')
 

We now have a module object bound to the variable hello_mod ; you can check that it really is a module and has the correct name — “hello” — in the interpreter:

hello_mod<module 'hello' (built-in)>
 

At this point, the new module is simply a blank slate; we can stick anything into it that we like. So let’s define the say_hello() function we’re going to use:

def say_hello():
    print "Hello"
 

And then add it to our hello module:

hello_mod.say_hello = say_hello
 

You can call this function and verify that it works:

hello_mod.say_hello()
 

Putting it all together

Of course, we still need to make our new module importable via the name “hello”, but armed with an understanding of sys.modules this is easy:

import sys
sys.modules.setdefault('hello', hello_mod)

>>><module 'hello' (built-in)>
 

We’re using setdefault() here instead of assigning directly to sys.modules[‘hello’] , because if there’s already a loaded module named hello we shouldn’t overwrite it; the setdefault() method of a Python dictionary takes a key and and a value, and then either inserts the value into the dictionary with the given key, if that key wasn’t already in use in the dictonary, or else does nothing to the dictionary. In either case it returns the value which ends up in the dictionary, which provides an easy way to figure out if you added a new value or not. In this case, the return value of setdefault() was the module we just created, so we know it was added to sys.modules successfully.

And now we can use the “magic”:

import hello
 
hello.say_hello()

>>>Hello

 

This works because our dynamically-created module object is now in sys.modules under the name “hello”; since it’s in there, Python will simply return it any time we say import hello and never bother checking the file system to see if a “real” module of that name exists on the Python path. We can even use the alternate from syntax to import just the say_hello() function:

from hello import say_hello
say_hello()

>>>Hello
 

Once again, Python is simply giving us back the contents of the module object we created in memory; the fact that it exists in sys.modules again bypasses any need to check the file system. And as soon as you exit the Python interpreter, the hello module will simply disappear; since it only ever existed in memory inside this single Python process, it will go away as soon as that Python process exits.

And now you know

At this point you can probably work out how Django — back in the 0.90 and 0.91 days — used to create the “magic” model modules which were importable from django.models ; there was a lot more work going on to build up the things which eventually lived inside that module, but ultimately it boiled down to the same two things we just did: createing a new module object with types.ModuleType , and making it importable by inserting it into sys.modules .

I can’t stress enough that this is something you probably shouldn’t ever do in real-world code, because — as the example of Django’s old-style model system shows — it’s confusing and counterintuitive to mysteriously create modules where people aren’t expecting them. And messing with sys.modules , unless you really know what you’re doing, can also be dangerous; if you’re not careful you might accidentally delete or overwrite the entry for a module you were relying on, and then you’ll be in a real pickle.

But knowing how the process works — even if you never actually use it — helps to turn this from “magic” into a fairly straightforward application of a Python feature, and provides a useful glimpse into some of Python’s fundamental workings: knowing how Python’s import mechanism works, for example, is incredibly important and handy for a broad range of Python programming tasks, and shows off a major part of Python’s sometimes-downplayed dynamic nature.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源
大学生在线租房平台管理系统按照操作主体分为管理员和用户。管理员的功能包括报修管理、报修评价管理、字典管理、房东管理、房屋管理、房屋收藏管理、房屋留言管理、房屋租赁管理、租房论坛管理、公告信息管理、留言板管理、用户管理、管理员管理。用户的功能等。该系统采用了Mysql数据库,Java语言,Spring Boot框架等技术进行编程实现。 大学生在线租房平台管理系统可以提高大学生在线租房平台信息管理问题的解决效率,优化大学生在线租房平台信息处理流程,保证大学生在线租房平台信息数据的安全,它是一个非常可靠,非常安全的应用程序。 管理员权限操作的功能包括管理公告,管理大学生在线租房平台信息,包括房屋管理,培训管理,报修管理,薪资管理等,可以管理公告。 房屋管理界面,管理员在房屋管理界面中可以对界面中显示,可以对房屋信息的房屋状态进行查看,可以添加新的房屋信息等。报修管理界面,管理员在报修管理界面中查看报修种类信息,报修描述信息,新增报修信息等。公告管理界面,管理员在公告管理界面中新增公告,可以删除公告。公告类型管理界面,管理员在公告类型管理界面查看公告的工作状态,可以对公告的数据进行导出,可以添加新公告的信息,可以编辑公告信息,删除公告信息。
基于hal库的OLED显示屏驱动C语言实现源码.zip 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我! 基于hal库的OLED显示屏驱动C语言实现源码.zip基于hal库的OLED显示屏驱动C语言实现源码.zip基于hal库的OLED显示屏驱动C语言实现源码.zip基于hal库的OLED显示屏驱动C语言实现源码.zip基于hal库的OLED显示屏驱动C语言实现源码.zip基于hal库的OLED显示屏驱动C语言实现源码.zip基于hal库的OLED显示屏驱动C语言实现源码.zip基于hal库的OLED显示屏驱动C语言实现源码.zip基于hal库的OLED显示屏驱动C语言实现源码.zip基于hal库的OLED显示屏驱动C语言实现源码.zip基于hal库的OLED显示屏驱动C语言实现源码.zip基于hal库的OLED显示屏驱动C语言实现源码.zip基于hal库的OLED显示屏驱动C语言实现源码.zip
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值