过去几周我一直在绞尽脑汁,我似乎无法理解它。我希望你们这里的人能给我一些清晰的信息。
小背景 我已经构建了一个API来帮助为大型网站提供服务,并且像我们所有人一样,正在努力保持API尽可能高效。这种效率的一部分是在创建请求时不要一次又一次地创建包含自定义业务逻辑的对象(例如:服务类)。为了给出一些个人背景,我来自Java世界,所以我使用IoC或DI来帮助处理对象创建和注入我的类,以确保不会在每个请求的基础上反复创建类。 / p>
我正在阅读 在查看许多Python IoC和DI帖子时,我对如何最好地创建给定类的方式感到困惑,而不必担心服务器根据可能处理的请求数量而导致过多的对象过载。
有些人说IoC或DI确实不需要。但是当我运行我的Django应用程序时,我发现除非我构建我想要全局(文件顶部)的对象,以便后面使用views.py而不是在每个视图类中或者在views.py中使用def,我运行创建多个类的更改相同类型的,从我的理解,将导致服务器上的内存膨胀。
那么什么是pythonic的正确方法来防止对象被反复建造?我是否应该投资使用IoC / DI?我可以安全地依赖设置我的service.py文件来包含def而不是包含def的类吗?垃圾收集器是否有效,所以我甚至不用担心它。
我故意没有在这篇文章中放置任何代码,因为这似乎是一般性问题,但如果有帮助,我可以提供一些代码示例。
由于 来自一个想要尽可能像pythonic的混乱工程师
答案 0 :(得分:9)
你来自一个需要所有东西的背景,我也用Java编写了网络应用程序,有时候我更难忘记旧事物而不是学习新事物,我明白。
在Python / Django中,除非你需要很多实例并且需要保持状态,否则你不会创建任何类。
对于一种情况并非如此的服务,有时您会注意到类似Java的Web应用程序中的一些服务是单例服务,这只是一种解决方法,而且是Python中相当大的反模式
Python足够灵活,因此不需要“服务类”,你只需要一个带有许多函数的Python模块(例如services.py
),强调是一种能够以完全无状态的方式接受某种东西,返回某种东西的功能。
# services.py
# this is a module, doesn't keep any state within,
# it may read and write to the DB, do some processing etc but doesn't remember things
def get_scores(student_id):
return Score.objects.filter(student=student_id)
# views.py
# receives HTTP requests
def view_scores(request, student_id):
scores = services.get_scores(student_id)
# e.g. use the scores queryset in a template return HTML page
请注意,如果你需要更换服务,你只需要交换一个Python模块(实际上只是一个文件),因此Pythonistas几乎不会打扰显式接口和其他抽象。
现在,根据每个“django工作进程”,您将拥有一个services
模块,该模块会反复用于所有进入的请求,以及使用Score
查询集时不再在记忆中指出,它会被清理干净。
我看到了你的另一篇文章,好吧,为每个请求实例化一个ScoreService
对象,或者在全局范围内保留它的实例是不必要的,上面的例子用内存中的一个模块来完成工作,而且我们不需要我们聪明一点。
如果 需要在几个请求之间保持状态,那么将它们保存在ScoreService
的联机实例中无论如何都是个坏主意,因为现在每个用户可能需要一个实例,那是不可行的(保留上下文的在线对象太多)。更不用说除非你有一些共享机制,否则只能从同一个进程访问该实例。
如果您希望保持状态中间请求,则将状态保留在数据存储中,当请求进入时,再次点击services
模块以从数据存储区返回上下文,拿起你离开它的地方并开展业务,返回你的HTTP响应,然后未使用的东西将被垃圾收集。
重点是保持无状态,在任何给定的django进程上可以处理任何给定的HTTP请求,并且在返回响应并且对象超出范围之后,所有状态对象都被垃圾收集。
这可能不是我们可以提取的最快的请求/响应周期,但它可以扩展为地狱
我建议你看看一些开源的Django项目,看看它们是如何组织的,你会看到很多你正在捣乱的东西,Djangonauts只是不打扰。