GVKun编程网logo

如何实现 Python 的惰性导入-lazy import(python惰性计算)

2

如果您对如何实现Python的惰性导入-lazyimport和python惰性计算感兴趣,那么这篇文章一定是您不可错过的。我们将详细讲解如何实现Python的惰性导入-lazyimport的各种细节,

如果您对如何实现 Python 的惰性导入-lazy importpython惰性计算感兴趣,那么这篇文章一定是您不可错过的。我们将详细讲解如何实现 Python 的惰性导入-lazy import的各种细节,并对python惰性计算进行深入的分析,此外还有关于"from pymongo import Connection" (to import mongo.connection using python) , got "500 Internal Server Error"、2spring 注解:@Lazy,@Conditional,@import,FactoryBean 接口、@import 与 #import - iOS 7、@Lazy(true) 在 application.yml 中没有 spring.main.lazy-initialization=true 就不能工作的实用技巧。

本文目录一览:

如何实现 Python 的惰性导入-lazy import(python惰性计算)

如何实现 Python 的惰性导入-lazy import(python惰性计算)

如果你的 Python 程序程序有大量的 import,而且启动非常慢,那么你应该尝试懒导入,本文分享一种实现惰性导入的一种方法。虽然 PEP0690[1] 已经提案让 Python 编译器(-L) 或者标准库加入这个功能,但目前的 Python 版本还未实现。

众所周知,Python 应用程序在执行用户的实际操作之前,会执行 import 操作,不同的模块可能来自不同的位置,某些模块的运行可能非常耗时,某些模块可能根本不会被用户调用,因此很多模块的导入纯粹是浪费时间。

因此我们需要惰性导入,当应用惰性导入时,运行 import foo 仅仅会把名字 foo 添加到全局的全名空间(globals())中作为一个懒引用(lazy reference),编译器遇到任何访问 foo 的代码时才会执行真正的 import 操作。类似的,from foo import bar 会把 bar 添加到命名空间,当遇到调用 bar 的代码时,就把 foo 导入。

写代码实现

那怎么写代码实现呢?其实不必写代码实现,已经有项目实现了懒导入功能,那就是 TensorFlow,它的代码并没有任何三方库依赖,我把它放到这里,以后大家需要懒导入的时候直接把 LazyLoader[2] 类复制到自己的项目中去即可。

源代码如下:

# Code copied from https://github.com/tensorflow/tensorflow/blob/master/tensorflow/python/util/lazy_loader.py
"""A LazyLoader class."""

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import importlib
import types


class LazyLoader(types.ModuleType):
"""Lazily import a module, mainly to avoid pulling in large dependencies.

`contrib`, and `ffmpeg` are examples of modules that are large and not always
needed, and this allows them to only be loaded when they are used.
"""

# The lint error here is incorrect.
def __init__(self, local_name, parent_module_globals, name):# pylint: disable=super-on-old-class
self._local_name = local_name
self._parent_module_globals = parent_module_globals

super(LazyLoader, self).__init__(name)

def _load(self):
# Import the target module and insert it into the parent''s namespace
module = importlib.import_module(self.__name__)
self._parent_module_globals[self._local_name] = module

# Update this object''s dict so that if someone keeps a reference to the
# LazyLoader, lookups are efficient (__getattr__ is only called on lookups
# that fail).
self.__dict__.update(module.__dict__)

return module

def __getattr__(self, item):
module = self._load()
return getattr(module, item)

def __dir__(self):
module = self._load()
return dir(module)
登录后复制

代码说明:

类 LazyLoader 继承自 types.ModuleType,初始化函数确保惰性模块将像真正的模块一样正确添加到全局变量中,只要真正用到模块的时候,也就是执行 __getattr__ 或 __dir__ 时,才会真正的 import 实际模块,更新全局变量以指向实际模块,并且将其所有状态(__dict__)更新为实际模块的状态,以便对延迟加载的引用,加载模块不需要每次访问都经过加载过程。

代码使用:

正常情况下我们这样导入模块:

import tensorflow.contrib as contrib
登录后复制

其对应的惰性导入版本如下:

contrib = LazyLoader(''contrib'', globals(), ''tensorflow.contrib'')
登录后复制

PEP0690 建议的做法

PEP0690 的提案是在编译器( C 代码)层面实现,这样性能会更好。其使用方法有两种。

其一

一种方式是执行 Python 脚本时加入 -L 参数,比如有两个文件 spam.py 内容如下:

import time
time.sleep(10)
print("spam loaded")
登录后复制

egg.py 内容如下:

import spam
print("imports done")
登录后复制

正常导入情况下,会等 10 秒后先打印 "spam loaded",然后打印 "imports done",当执行 python -L eggs.py 时,spam 模块永远不会导入,应用 spam 模块压根就没有用到。如果 egg.py 内容如下:

import spam
print("imports done")
spam
登录后复制

当执行 python -L eggs.py 时会先打印 "imports done",10 秒之后打印 "spam loaded")。

其二

另一种方式是调用标准库 importlib 的方法:

import importlib 
importlib.set_lazy_imports(True)
登录后复制

如果某些模块不能懒加载,需要排除,可以这样

import importlib 
importlib.set_lazy_imports(True,excluding=["one.mod", "another"])
登录后复制

还可以这样:

from importlib import eager_imports

with eager_imports():
import foo
import bar
登录后复制

最后的话

经过专业人士在真实的 Python 命令行程序上做测试,应用惰性导入后,可以使启动时间提高 70%,内存使用减少 40%,非常可观了。

参考资料

[1]PEP0690: https://github.com/python/peps/blob/main/pep-0690.rst

[2]LazyLoader: https://github.com/tensorflow/tensorflow/blob/master/tensorflow/python/util/lazy_loader.py

以上就是如何实现 Python 的惰性导入-lazy import的详细内容,更多请关注php中文网其它相关文章!

"from pymongo import Connection" (to import mongo.connection using python) , got "500 Internal Server Error"

I created the /var/www/cgi-bin/test.py in my web server machine (Linux). The service of mongoDB "mongod" is running.

When I run the test.py locally, "./test.py", I could get the correct result.

But when I use the URL: http://xxxxxx.compute-1.amazonaws.com/cgi-bin/python_test/test.py to run the test.py, I will get the "500 Internal Server Error". 

If I remove the line "from pymongo import Connection", and use the URL above to access, I won''t get the 500 Internal server error. So, it should be the problem when I import the pymongo.connection.

Is it the problem of any configuration issue? Thanks so much for your help

========== test.py ==============

#!/usr/bin/python
import cgi
import sys
sys.path.append("/home/ec2-user/mongo-python-driver-2.6.3/")

#import pymongo.connection
from pymongo import Connection
def main():
        print "Content-type: text/html\r\n\r\n"
        form = cgi.FieldStorage()
        name = form.getvalue(''ServiceCode'')
#       name = "abcddd"
#       con = Connection()
#       db = con.test
#       posts = db.post

#       print name
        if form.has_key("ServiceCode") and form["ServiceCode"].value!="":
                print"<h1>Hello", form["ServiceCode"].value,"</h1>"
        else:
                print"<h1>Error! Please enter first name. </h1>"

 .....


2spring 注解:@Lazy,@Conditional,@import,FactoryBean 接口

2spring 注解:@Lazy,@Conditional,@import,FactoryBean 接口

大致的工程内容也来源于上一篇博文! 

https://www.cnblogs.com/Mrchengs/p/10108603.html 

 

 1.@Lazy 懒加载

 懒加载:针对单实例的

 单实例 bean,默认在容器启动的时候创建对象

 懒加载就是:容器启动的时候不创建对象,在第一次获取 bean 的时候创建对象,并且初始化、

 

 Config2.class

@Configuration
public class Config2 {
     @Bean("per")
     public Person person(){
            System.out.println("person对象创建完成");
           return new Person("MrChengs",20);
     }
}

 测试

     @Test
     public void test2(){
           ApplicationContext app = new  AnnotationConfigApplicationContext(Config2.class);
           String [] names = app.getBeanDefinitionNames();
           System.out.println("容器创建完成...");
     }

此时并没有去获取 Person 对象!

此时容器创建之后就会实例化对象

person对象创建完成
容器创建完成...

 

 使用懒加载:

@Configuration
public class Config2 {
     @Lazy
     @Bean("per")
     public Person person(){
           System.out.println("person对象创建完成");
           return new Person("MrChengs",20);
     }
}

 测试:

容器创建完成...

 

 2..@Conditional

按照一定的条件判断, 满足条件给容器注册
可以在类上也可以在方法上
放置在类上,满足 条件,配置的所有的 bean 都会生效

 

 假设在 windows 和 Linux 操作系统获取自动的注册信息

@Configuration
public class Config2 {
     @Lazy
     @Bean("per")
     public Person person(){
           System.out.println("person对象创建完成");
           return new Person("MrChengs",20);
     }
     
     //按照一定的条件判断,满足条件给容器注册
     
     @Conditional({LinuxCondition.class})
     @Bean("person1")
     public Person person1(){
           return new Person("Mr",12);
     }
     
     @Conditional({WindowsCondition.class})
     @Bean("person2")
     public Person person2(){
           return new Person("Mx",20);
     }
}
public class LinuxCondition implements Condition{
     //ConditionContext:判条件能使用的上下文
     //AnnotatedTypeMetadata:注释信息
     public boolean matches(ConditionContext context,  AnnotatedTypeMetadata metadata) {
           
           //能获取到IOC容器使用的beanfactory
           ConfigurableListableBeanFactory c =  context.getBeanFactory();
           //获取加载器
           ClassLoader classLoader = context.getClassLoader();
           //获取当前的环境信息
           //Environment environment =   (Environment)  context.getEnvironment();
           //获取bean定义注册的类
           BeanDefinitionRegistry resistroy =  context.getRegistry();
           
       //获取当前的操作系统 String name
= context.getEnvironment().getProperty("os.name"); if(name.contains("Linux")){ return true; } return false; } }
public class WindowsCondition implements Condition{
     //ConditionContext:判条件能使用的上下文
     //AnnotatedTypeMetadata:注释信息
     public boolean matches(ConditionContext context,  AnnotatedTypeMetadata metadata) {
           
           //能获取到IOC容器使用的beanfactory
           ConfigurableListableBeanFactory c =  context.getBeanFactory();
           //获取加载器
           ClassLoader classLoader = context.getClassLoader();
           //获取当前的环境信息
           //Environment environment =   (Environment)  context.getEnvironment();
           //获取bean定义注册的类
           BeanDefinitionRegistry resistroy =  context.getRegistry();
           
           String name =  context.getEnvironment().getProperty("os.name");
           if(name.contains("Win")){
                return true;
           }
           return false;
     }
}
     @Test
     public void test3(){
           ApplicationContext app = new  AnnotationConfigApplicationContext(Config2.class);
           String [] names =  app.getBeanNamesForType(Person.class);
           for(String name : names){
                System.out.println(name);
           }
           System.out.println("容器创建完成...");
     }
per
person2
容器创建完成...

 

3.@import

快速的给容器中导入一个组建
默认 创建的是 bean 是组建的全类名
@Configuration
@Import(Person.class)
public class Config2 {

}
     @Test
     public void test3(){
           ApplicationContext app = new  AnnotationConfigApplicationContext(Config2.class);
           String [] names =  app.getBeanNamesForType(Person.class);
           for(String name : names){
                System.out.println(name);
           }
           System.out.println("容器创建完成...");
     }
coom.MrChengs.bean.Person
容器创建完成...

 

源码:

public @interface Import {
     /**
      * {@link Configuration}, {@link ImportSelector}, {@link  ImportBeanDefinitionRegistrar}
      * or regular component classes to import.
      */
     Class<?>[] value();
}

 

可以同时传入多个

@Import({Person.classxxxxx})

直接注入到容器中

 

ImportSelector

是一个接口

public class MyImportSelector implements ImportSelector{
     //返回值就是需要导入到容器中的全类名
     //AnnotationMetadata : 就是获取标注@Import()注解类的所有信息
     public String[] selectImports(AnnotationMetadata  importingClassMetadata) {
           
           
           return new String[]{"coom.MrChengs.bean.Person"};
     }
}
@Configuration
@Import({MyImportSelector.class})
public class Config2 {
}
@Test
     public void test3(){
           ApplicationContext app = new  AnnotationConfigApplicationContext(Config2.class);
           String [] names = app.getBeanDefinitionNames();
           for(String name : names){
                System.out.println(name);
           }
           System.out.println("容器创建完成...");
     }
config2
coom.MrChengs.bean.Person
容器创建完成...

 

ImportBeanDefinitionRegistrar 接口

public class MyImportBeanDefinitionRegistrar implements  ImportBeanDefinitionRegistrar {
     //AnnotationMetadata:当前类的注解信息
     //BeanDefinitionRegistry:注册类
     public void registerBeanDefinitions(AnnotationMetadata  importingClassMetadata, BeanDefinitionRegistry registry) {
           
           //coom.MrChengs.bean.Person
           //判断当前类是否有下面的这个bean
           boolean a =  registry.containsBeanDefinition("coom.MrChengs.bean.Person");
           //如果没有我们进行注册
           if(!a){
                RootBeanDefinition beanDefinition = new  RootBeanDefinition(Person.class);
                //指定bean的名字
                //注册一个bean
                registry.registerBeanDefinition("peson",  beanDefinition );
           }
     }
}
@Configuration
@Import({MyImportBeanDefinitionRegistrar.class})
public class Config2 {
}
@Test
     public void test3(){
           ApplicationContext app = new  AnnotationConfigApplicationContext(Config2.class);
           String [] names = app.getBeanDefinitionNames();
           for(String name : names){
                System.out.println(name);
           }
           System.out.println("容器创建完成...");
     }
config2
peson
容器创建完成...

 

4.FactoryBean 接口

public class PersonFactoryBean implements FactoryBean<Person>{

     //返回一个person对象,这个对象会添加到容器中
     public Person getObject() throws Exception {
           // TODO Auto-generated method stub
           return new Person();
     }

     //返回类型
     public Class<?> getObjectType() {
           // TODO Auto-generated method stub
           return Person.class;
     }

     //是单例吗?
     public boolean isSingleton() {
           // TODO Auto-generated method stub
           return false;
     }
}
@Configuration
public class Config2 {
     
     @Bean
     public PersonFactoryBean personFactoryBean(){
           return new PersonFactoryBean();
     }
}
     @Test
     public void test3(){
           ApplicationContext app = new  AnnotationConfigApplicationContext(Config2.class);
           String [] names = app.getBeanDefinitionNames();
           for(String name : names){
                System.out.println(name);
           }
           Object name =  app.getBean("personFactoryBean").getClass();
           System.out.println(name);
           System.out.println("容器创建完成...");
     }
config2
personFactoryBean
class coom.MrChengs.bean.Person   -> Object name =  app.getBean("personFactoryBean").getClass();
容器创建完成...

得到的是 Person 对象

 

默认得到的是 getObject 的对象
 
给 id 前面加一个 & 符号得到的是对象本身
Object name = app.getBean("&personFactoryBean").getClass();
class coom.MrChengs.bean.PersonFactoryBean

 

@import 与 #import - iOS 7

@import 与 #import - iOS 7

我正在使用一些新的 iOS 7 功能并使用 WWDC 视频“在 iOS 上实现 Engaging
UI”中讨论的一些图像效果。为了在会话的源代码中产生模糊效果,UIImage通过导入 UIKit 的类别进行了扩展,如下所示:

@import UIKit;

我想我在另一个会话视频中看到了一些关于此的内容,但我找不到它。我正在寻找有关何时使用它的任何背景信息。它只能与 Apple
框架一起使用吗?使用这个编译器指令的好处是否足以让我回去更新旧代码?

答案1

小编典典

这是一个称为 模块* 或“语义导入”的新功能。有关 Session
205和404的WWDC
2013视频中有更多信息。这是预编译头文件的一种更好的实现。
您可以将模块与 iOS 7 和 Mavericks 中的任何系统框架一起使用。
模块是框架可执行文件及其头文件的封装,被吹捧为比.
*#import

使用的一大优点@import你不需要在项目设置中添加框架,它是自动完成的
。这意味着您可以跳过单击加号按钮并搜索框架(金色工具箱)的步骤,然后将其移至“框架”组。它将许多开发人员从神秘的“链接器错误”消息中解救出来。

您实际上不需要使用@import关键字。如果您选择使用模块,所有#import#include指令都将被映射为@import自动使用。这意味着您不必更改源代码(或从其他地方下载的库的源代码)。据说使用模块也可以提高构建性能,特别是如果您没有很好地使用
PCH 或者您的项目有很多小源文件。

模块是为大多数 Apple 框架(UIKit、MapKit、GameKit 等)预先构建的。您可以将它们与您自己创建的框架一起使用:如果您在 Xcode
中创建 Swift 框架,它们会自动创建,您可以为任何 Apple 或 3rd-party
library自己手动创建一个“.modulemap”文件。

您可以使用代码完成来查看可用框架的列表:

在此处输入图像描述

Xcode 5 的新项目中默认启用模块
。要在旧项目中启用它们,请进入您的项目构建设置,搜索“模块”并将“启用模块”设置为“是”。“链接框架”也应该是“是”:

您必须使用 Xcode 5 和 iOS 7 或 Mavericks SDK,但您仍然可以为较旧的操作系统(比如 iOS 4.3 或其他)发布。
模块不会更改您的代码的构建方式或任何源代码。


来自 WWDC 幻灯片:

  • 导入框架的完整语义描述
  • 不需要解析标题
  • 导入框架界面的更好方法
  • 加载二进制表示
  • 比预编译头文件更灵活
  • 不受本地宏定义的影响(例如#define readonly 0x01
  • 默认为新项目启用

要显式使用模块:

替换#import <Cocoa/Cocoa.h>@import Cocoa;

您也可以使用此表示法仅导入一个标头:

@import iAd.ADBannerView;

Xcode 中的子模块会自动完成。

@Lazy(true) 在 application.yml 中没有 spring.main.lazy-initialization=true 就不能工作

@Lazy(true) 在 application.yml 中没有 spring.main.lazy-initialization=true 就不能工作

如何解决@Lazy(true) 在 application.yml 中没有 spring.main.lazy-initialization=true 就不能工作?

我真的对 spring boot 2.2 中的延迟初始化行为感到困惑

我在配置类中定义了 2 个 spring bean,我想将它们与项目中的其他 @Component 类一起延迟初始化。

如果我将 @Lazy 添加到我的 bean 中,并且 @Lazy 应该可以工作。 但是如果我不在 application.yml 中添加 spring.main.lazy-initialisation,它会急切地初始化

真的很困惑。请帮助。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

关于如何实现 Python 的惰性导入-lazy importpython惰性计算的介绍现已完结,谢谢您的耐心阅读,如果想了解更多关于"from pymongo import Connection" (to import mongo.connection using python) , got "500 Internal Server Error"、2spring 注解:@Lazy,@Conditional,@import,FactoryBean 接口、@import 与 #import - iOS 7、@Lazy(true) 在 application.yml 中没有 spring.main.lazy-initialization=true 就不能工作的相关知识,请在本站寻找。

本文标签: