组织一个必须共享内部状态的大型Python项目? 我目前正在移植一个相当大的Perl,问题是它使用了小的Perl技巧,使代码可以用于使用ing。我对Python也做了同样的工作,使代码库成为importing的一个大模块。很长一段时间以来,我一直牢牢掌握Python,但我没有使用Python编写的大型项目的经验,这些项目需要在维护内部状态的同时访问自身的其他部分

组织一个必须共享内部状态的大型Python项目? 我目前正在移植一个相当大的Perl,问题是它使用了小的Perl技巧,使代码可以用于使用ing。我对Python也做了同样的工作,使代码库成为importing的一个大模块。很长一段时间以来,我一直牢牢掌握Python,但我没有使用Python编写的大型项目的经验,这些项目需要在维护内部状态的同时访问自身的其他部分,python,project-management,code-organization,Python,Project Management,Code Organization,我还没有尝试在一行中简单地导入整个内容(importcore),但我知道我目前没有以最好的方式进行导入。下面是主脚本中的一个示例,它设置了所有动作: self.Benchmark = Benchmark(self) self.Exceptions = Exceptions self.Settings = Settings(self) self.Cache = Cache(self) self.Deal = Deal(self) self.Utils = Utils(self) self.F

我还没有尝试在一行中简单地导入整个内容(
importcore
),但我知道我目前没有以最好的方式进行导入。下面是主脚本中的一个示例,它设置了所有动作:

self.Benchmark = Benchmark(self)

self.Exceptions = Exceptions

self.Settings = Settings(self)
self.Cache = Cache(self)

self.Deal = Deal(self)
self.Utils = Utils(self)
self.FileParsers = FileParsers(self)
self.Network = Network(self)
self.Plugins = Plugins(self)
self.Misc = Misc(self)
这很有效,但我不满意。现在,主类脚本导入
核心
模块的每一部分,并创建所包含类的一个实例,将自身作为参数传递给这些类中的
\uuuuu init\uuuu
。像这样:

class FileParsers:
    def __init__(self, parent):
        self.parent = parent
现在,该类中的代码可以通过父类访问整个代码库的其余部分

self.parent.Settings.loadSysConfig()
因此,我的问题是:考虑到上述情况,重组项目和重构代码的最佳方式是什么,以使其保留当前访问所有其他内容的能力?代码是非常非关键的,所以我不太担心内部数据的完整性,我只是不喜欢以如此丑陋的方式遍历父类。这些长链也会降低代码的速度


编辑:哇,忘了这些:两个项目的SVN回购的链接。我的,我正在移植的项目是.

如果不能够真正地看到代码,很难说清楚,但是你应该只考虑导入每个模块在那个模块中使用的项目。有一个长长的进口清单并不罕见——以下是我自己网站上的一个例子:

# standard
import inspect
import linecache
import neo_cgi
import neo_cs
import neo_util
import os
import random
import sys
import time
from _apache import SERVER_RETURN
from mod_python import apache
from mod_python import util
from mod_python.util import FieldStorage
from os.path import dirname, isfile, join, splitext

# set up path
pydir = dirname(__file__)
if pydir not in sys.path:
    sys.path.append(pydir)

# things I wrote
import auth
import handlers.accounts, handlers.publish, handlers.standard
import logger
import markup
import programs
import summarize
from auth import check_auth
from common import hdf_iterate, load_hdf_cgi_vars, load_hdf_common_vars
from common import hdf_insert_value, hdf_insert_list, hdf_insert_dict
from handlers import chain, farm, opt
from handlers import URIPrefixFilter
from handlers.standard import TabBarHandler
我相信很多较大的模块都有更长的列表

在您的情况下,可能有一个带有单例对象(或将设置作为模块属性)的
设置
模块,并且


如果不能够真正地看到代码,很难判断,但您可能应该考虑导入每个模块使用的项,在该模块中。有一个长长的进口清单并不罕见——以下是我自己网站上的一个例子:

# standard
import inspect
import linecache
import neo_cgi
import neo_cs
import neo_util
import os
import random
import sys
import time
from _apache import SERVER_RETURN
from mod_python import apache
from mod_python import util
from mod_python.util import FieldStorage
from os.path import dirname, isfile, join, splitext

# set up path
pydir = dirname(__file__)
if pydir not in sys.path:
    sys.path.append(pydir)

# things I wrote
import auth
import handlers.accounts, handlers.publish, handlers.standard
import logger
import markup
import programs
import summarize
from auth import check_auth
from common import hdf_iterate, load_hdf_cgi_vars, load_hdf_common_vars
from common import hdf_insert_value, hdf_insert_list, hdf_insert_dict
from handlers import chain, farm, opt
from handlers import URIPrefixFilter
from handlers.standard import TabBarHandler
我相信很多较大的模块都有更长的列表

在您的情况下,可能有一个带有单例对象(或将设置作为模块属性)的
设置
模块,并且

或者别的什么

重组项目和重构代码的最佳方式是什么,以使其保留当前访问其他所有内容的能力

我认为您实际上已经非常接近了,并且可能比许多Python项目要好,在这些项目中,他们只假设应用程序只有一个实例,并将特定于应用程序的值存储在全局模块或单实例中

(对于许多简单的应用程序来说,这是可以的,但实际上最好是能够将所有内容捆绑到一个应用程序对象中,该对象拥有需要了解应用程序状态的所有内部类和方法。)

从上面代码的外观来看,我要做的第一件事是排除那些不是应用程序核心能力的模块和类,这些模块和类不一定需要访问应用程序的状态。像“Utils”和“Misc”这样的名字听起来很可疑,因为它们的许多内容实际上并不特定于你的应用程序;它们可能被重构成单独的独立模块,或者包中只有静态函数的子模块,而不依赖于应用程序状态

接下来,我将把主所有者应用程序类放在包的_init__uuu.py中,而不是放在“主脚本”中。然后,通过运行脚本或解释器,您可以获得应用程序的完整实例,如下所示:

import myapplication

a= myapplication.Application()

您还可以考虑将任何基本部署设置从设置类移动到初始化器:

a= myapplication.Application(basedir= '/opt/myapp', site= 'www.example.com', debug= False)
(如果您只有一组可能的设置,并且每次实例化Application()时都会得到相同的设置,那么封装整个应用程序的所有功能都没有什么用处;您也可以简单地使用模块全局变量。)

我对我的一些应用程序所做的是将所拥有的类猴子补丁自己变成所有者应用程序对象的实际成员:

# myapplication/__init__.py

class Application(object):
    def __init__(self, dbfactory, debug):
        # ...
        self.mailer= self.Mailer(self)
        self.webservice= self.Webservice(self)
        # ...

import myapplication.mailer, myapplication.webservice


# myapplication/mailer.py

import myapplication

class Mailer(object):
    def __init__(self, owner):
        self.owner= owner

    def send(self, message, recipients):
        # ...

myapplication.Application.Mailer= Mailer
然后,通过替换/子类化内部类,可以从外部扩展、更改或配置应用程序:

import myapplication

class MockApplication(myapplication.Application):
    class Mailer(myapplication.Application.Mailer):
        def send(self, message, recipients):
            self.owner.log('Mail send called (not actually sent)')
            return True
我并不担心内部数据的完整性

不,这是Python而不是Java:我们不太担心邪恶的程序员使用他们不应该使用的属性和方法,我们只是在名称的开头加上“u”,让它成为对所有人的适当警告

这些长链也会降低代码的速度

不太明显。可读性是重要因素;其他任何事情都是过早的优化

重组项目和重构代码的最佳方式是什么,以使其保留当前访问其他所有内容的能力

我认为您实际上已经非常接近了,并且可能比许多Python项目要好,在这些项目中,他们只假设应用程序只有一个实例,并将特定于应用程序的值存储在全局模块或单实例中

(对于许多简单的应用程序来说,这是可以的,但实际上最好是能够将所有内容捆绑到一个应用程序对象中,该对象拥有需要了解应用程序状态的所有内部类和方法。)

从上面代码的外观来看,我要做的第一件事是排除那些不是应用程序核心能力的模块和类,这些模块和类不一定需要访问应用程序的状态。像“Utils”和