วิธี Pythonic ส่วนใหญ่ในการจัดเตรียมตัวแปรการกำหนดค่าส่วนกลางใน config.py? [ปิด]


100

ในภารกิจที่ไม่มีที่สิ้นสุดของฉันในเรื่องง่าย ๆ ที่ซับซ้อนเกินไปฉันกำลังค้นคว้าวิธี 'Pythonic' ส่วนใหญ่เพื่อจัดหาตัวแปรการกำหนดค่าส่วนกลางภายใน ' config.py ' ทั่วไปที่พบในแพ็คเกจไข่ Python

วิธีดั้งเดิม (aah, good ol ' #define !) มีดังนี้:

MYSQL_PORT = 3306
MYSQL_DATABASE = 'mydb'
MYSQL_DATABASE_TABLES = ['tb_users', 'tb_groups']

ดังนั้นการนำเข้าตัวแปรส่วนกลางด้วยวิธีใดวิธีหนึ่งต่อไปนี้:

from config import *
dbname = MYSQL_DATABASE
for table in MYSQL_DATABASE_TABLES:
    print table

หรือ:

import config
dbname = config.MYSQL_DATABASE
assert(isinstance(config.MYSQL_PORT, int))

มันสมเหตุสมผล แต่บางครั้งอาจจะยุ่งเล็กน้อยโดยเฉพาะอย่างยิ่งเมื่อคุณพยายามจำชื่อของตัวแปรบางตัว นอกจากนี้การจัดเตรียมออบเจ็กต์ "การกำหนดค่า"โดยมีตัวแปรเป็นคุณลักษณะอาจมีความยืดหยุ่น ดังนั้นการเป็นผู้นำจากไฟล์bpython config.py ฉันจึงมาพร้อมกับ:

class Struct(object):

    def __init__(self, *args):
        self.__header__ = str(args[0]) if args else None

    def __repr__(self):
        if self.__header__ is None:
             return super(Struct, self).__repr__()
        return self.__header__

    def next(self):
        """ Fake iteration functionality.
        """
        raise StopIteration

    def __iter__(self):
        """ Fake iteration functionality.
        We skip magic attribues and Structs, and return the rest.
        """
        ks = self.__dict__.keys()
        for k in ks:
            if not k.startswith('__') and not isinstance(k, Struct):
                yield getattr(self, k)

    def __len__(self):
        """ Don't count magic attributes or Structs.
        """
        ks = self.__dict__.keys()
        return len([k for k in ks if not k.startswith('__')\
                    and not isinstance(k, Struct)])

และ 'config.py' ที่นำเข้าคลาสและอ่านดังนี้:

from _config import Struct as Section

mysql = Section("MySQL specific configuration")
mysql.user = 'root'
mysql.pass = 'secret'
mysql.host = 'localhost'
mysql.port = 3306
mysql.database = 'mydb'

mysql.tables = Section("Tables for 'mydb'")
mysql.tables.users = 'tb_users'
mysql.tables.groups =  'tb_groups'

และใช้ในลักษณะนี้:

from sqlalchemy import MetaData, Table
import config as CONFIG

assert(isinstance(CONFIG.mysql.port, int))

mdata = MetaData(
    "mysql://%s:%s@%s:%d/%s" % (
         CONFIG.mysql.user,
         CONFIG.mysql.pass,
         CONFIG.mysql.host,
         CONFIG.mysql.port,
         CONFIG.mysql.database,
     )
)

tables = []
for name in CONFIG.mysql.tables:
    tables.append(Table(name, mdata, autoload=True))

ซึ่งดูเหมือนจะเป็นวิธีการจัดเก็บและดึงข้อมูลตัวแปรส่วนกลางภายในแพ็คเกจที่อ่านง่ายและยืดหยุ่นกว่า

ความคิดที่เลวร้ายที่สุดที่เคย? แนวทางปฏิบัติที่ดีที่สุดในการรับมือกับสถานการณ์เหล่านี้คืออะไร? อะไรคือสิ่งที่คุณวิธีการจัดเก็บและเรียกชื่อระดับโลกและตัวแปรภายในแพคเกจของคุณหรือไม่


3
คุณได้ตัดสินใจที่นี่แล้วว่าอาจจะดีหรือไม่ดี การกำหนดค่าสามารถจัดเก็บได้หลายวิธีเช่น JSON, XML, ไวยากรณ์ที่แตกต่างกันสำหรับ * nixes และ Windows เป็นต้น ขึ้นอยู่กับว่าใครเป็นคนเขียนไฟล์ config (เครื่องมือมนุษย์พื้นหลังอะไร) ไวยากรณ์ที่แตกต่างกันอาจเป็นที่ต้องการ ส่วนใหญ่แล้วอาจไม่ควรให้ไฟล์ config เขียนด้วยภาษาเดียวกับที่คุณใช้กับโปรแกรมของคุณเพราะมันให้อำนาจแก่ผู้ใช้มากเกินไป (อาจเป็นตัวคุณเอง แต่คุณเองก็อาจจำทุกอย่างไม่ได้ ผิดพลาดหลายเดือนข้างหน้า)
erikbwork

4
บ่อยครั้งที่ฉันเขียนไฟล์ config JSON สามารถอ่านโครงสร้าง python ได้อย่างง่ายดายและสร้างโดยเครื่องมือ ดูเหมือนว่าจะมีความยืดหยุ่นมากที่สุดและมีค่าใช้จ่ายเพียงอย่างเดียวคือการจัดฟันบางอย่างที่อาจสร้างความรำคาญให้กับผู้ใช้ ฉันไม่เคยเขียนไข่เลย บางทีนั่นอาจเป็นวิธีมาตรฐาน ในกรณีนั้นให้เพิกเฉยต่อความคิดเห็นของฉันด้านบน
erikbwork

1
คุณสามารถใช้ "vars (self)" แทน "self .__ dict __. keys ()"
Karlisson

1
อาจซ้ำกันได้แนวทางปฏิบัติที่ดีที่สุดในการใช้ไฟล์การตั้งค่าใน Python คืออะไร พวกเขาตอบว่า "เป็นไปได้หลายวิธีและมีเธรดจักรยานอยู่แล้ว config.py นั้นดีเว้นแต่คุณจะใส่ใจเรื่องความปลอดภัย"
Nikana Reklawyks

ฉันใช้python-boxแล้วดูคำตอบ
วิวัฒนาการ

คำตอบ:


5

ฉันทำอย่างนั้นครั้งเดียว ในที่สุดฉันพบว่าbasicconfig.py ที่เรียบง่ายของฉันเพียงพอสำหรับความต้องการของฉัน คุณสามารถส่งในเนมสเปซพร้อมกับออบเจ็กต์อื่น ๆ เพื่อใช้อ้างอิงได้ คุณยังสามารถส่งผ่านค่าเริ่มต้นเพิ่มเติมจากรหัสของคุณ นอกจากนี้ยังแมปแอตทริบิวต์และรูปแบบการแม็ปไวยากรณ์กับวัตถุการกำหนดค่าเดียวกัน


6
basicconfig.pyไฟล์เรียกดูเหมือนว่าจะได้ย้ายไปgithub.com/kdart/pycopia/blob/master/core/pycopia/...
พอล M Furley

ฉันรู้ว่านี่มีอายุไม่กี่ปี แต่ฉันเป็นมือใหม่และฉันคิดว่าไฟล์ config นี้เป็นสิ่งที่ฉันกำลังมองหาเป็นหลัก (อาจจะสูงเกินไป) และฉันอยากจะเข้าใจมันให้ดีขึ้น ฉันเพิ่งผ่านการเริ่มต้นConfigHolderด้วยการกำหนดค่าตามกำหนดที่ฉันต้องการตั้งค่าและส่งต่อระหว่างโมดูลหรือไม่
Jinx

@Jinx ณ จุดนี้ฉันจะใช้ (และกำลังใช้) ไฟล์ YAML และ PyYAML สำหรับการกำหนดค่า ฉันยังใช้โมดูลของบุคคลที่สามที่เรียกว่าconfitและสนับสนุนการรวมแหล่งที่มาหลายแหล่ง เป็นส่วนหนึ่งของโมดูลdevtest.configใหม่
Keith

57

เพียงแค่ใช้ประเภทในตัวเช่นนี้:

config = {
    "mysql": {
        "user": "root",
        "pass": "secret",
        "tables": {
            "users": "tb_users"
        }
        # etc
    }
}

คุณจะเข้าถึงค่าดังต่อไปนี้:

config["mysql"]["tables"]["users"]

หากคุณเต็มใจที่จะสละศักยภาพในการคำนวณนิพจน์ภายในแผนผังการกำหนดค่าของคุณคุณสามารถใช้YAMLและจบลงด้วยไฟล์กำหนดค่าที่อ่านได้มากขึ้นดังนี้:

mysql:
  - user: root
  - pass: secret
  - tables:
    - users: tb_users

และใช้ไลบรารีเช่นPyYAMLเพื่อแยกวิเคราะห์และเข้าถึงไฟล์ config


แต่โดยปกติคุณต้องการมีไฟล์กำหนดค่าที่แตกต่างกันจึงไม่มีข้อมูลการกำหนดค่าใด ๆ ในโค้ดของคุณ ดังนั้น´config´ จะเป็นไฟล์ JSON / YAML ภายนอกซึ่งคุณต้องโหลดจากดิสก์ทุกครั้งที่คุณต้องการเข้าถึงในทุกคลาส ฉันเชื่อว่าคำถามคือ "โหลดครั้งเดียว" และสามารถเข้าถึงข้อมูลที่โหลดได้เหมือนทั่วโลก คุณจะทำอย่างไรกับโซลูชันที่คุณแนะนำ
omni

3
ถ้าจะมีอะไรสักอย่างเพื่อเก็บข้อมูลไว้ในความทรงจำ ^^
cinatic

16

ฉันชอบโซลูชันนี้สำหรับแอปพลิเคชันขนาดเล็ก :

class App:
  __conf = {
    "username": "",
    "password": "",
    "MYSQL_PORT": 3306,
    "MYSQL_DATABASE": 'mydb',
    "MYSQL_DATABASE_TABLES": ['tb_users', 'tb_groups']
  }
  __setters = ["username", "password"]

  @staticmethod
  def config(name):
    return App.__conf[name]

  @staticmethod
  def set(name, value):
    if name in App.__setters:
      App.__conf[name] = value
    else:
      raise NameError("Name not accepted in set() method")

จากนั้นการใช้งานคือ:

if __name__ == "__main__":
   # from config import App
   App.config("MYSQL_PORT")     # return 3306
   App.set("username", "hi")    # set new username value
   App.config("username")       # return "hi"
   App.set("MYSQL_PORT", "abc") # this raises NameError

.. น่าจะชอบเพราะ:

  • ใช้ตัวแปรคลาส (ไม่มีวัตถุที่จะผ่านไปมา / ไม่จำเป็นต้องใช้ซิงเกิลตัน)
  • ใช้ห่อหุ้มในตัวชนิดและรูปลักษณ์ที่เหมือน (เป็น) เรียกวิธีบนApp,
  • มีการควบคุมการตั้งค่าของแต่ละบุคคลไม่เปลี่ยนรูป , Globals ไม่แน่นอนเป็นชนิดที่เลวร้ายที่สุดของ GlobalsGlobals
  • ส่งเสริมการเข้าถึง / การอ่านแบบเดิมและมีชื่อดีในซอร์สโค้ดของคุณ
  • เป็นคลาสที่เรียบง่าย แต่บังคับใช้การเข้าถึงแบบมีโครงสร้างอีกทางเลือกหนึ่งคือการใช้@propertyแต่ต้องใช้โค้ดการจัดการตัวแปรมากกว่าต่อรายการและอิงตามออบเจ็กต์
  • ต้องการการเปลี่ยนแปลงเพียงเล็กน้อยเพื่อเพิ่มรายการกำหนดค่าใหม่และตั้งค่าความไม่แน่นอน

- แก้ไข - : สำหรับแอปพลิเคชันขนาดใหญ่การจัดเก็บค่าในไฟล์ YAML (เช่นคุณสมบัติ) และการอ่านข้อมูลที่ไม่เปลี่ยนรูปเป็นแนวทางที่ดีกว่า (เช่นคำตอบของ blubb / ohaal ) สำหรับแอปพลิเคชันขนาดเล็กโซลูชันด้านบนนี้จะง่ายกว่า


9

แล้วการใช้คลาสล่ะ?

# config.py
class MYSQL:
    PORT = 3306
    DATABASE = 'mydb'
    DATABASE_TABLES = ['tb_users', 'tb_groups']

# main.py
from config import MYSQL

print(MYSQL.PORT) # 3306

8

คล้ายกับคำตอบของ blubb ฉันขอแนะนำให้สร้างด้วยฟังก์ชันแลมบ์ดาเพื่อลดโค้ด แบบนี้:

User = lambda passwd, hair, name: {'password':passwd, 'hair':hair, 'name':name}

#Col      Username       Password      Hair Color  Real Name
config = {'st3v3' : User('password',   'blonde',   'Steve Booker'),
          'blubb' : User('12345678',   'black',    'Bubb Ohaal'),
          'suprM' : User('kryptonite', 'black',    'Clark Kent'),
          #...
         }
#...

config['st3v3']['password']  #> password
config['blubb']['hair']      #> black

สิ่งนี้มีกลิ่นเหมือนคุณอาจต้องการสร้างชั้นเรียน

หรือตามที่ MarkM ระบุไว้คุณสามารถใช้ namedtuple

from collections import namedtuple
#...

User = namedtuple('User', ['password', 'hair', 'name']}

#Col      Username       Password      Hair Color  Real Name
config = {'st3v3' : User('password',   'blonde',   'Steve Booker'),
          'blubb' : User('12345678',   'black',    'Bubb Ohaal'),
          'suprM' : User('kryptonite', 'black',    'Clark Kent'),
          #...
         }
#...

config['st3v3'].password   #> passwd
config['blubb'].hair       #> black

3
passเป็นชื่อตัวแปรที่โชคร้ายเนื่องจากเป็นคำหลักด้วย
Thomas Schreiter

โอ้ใช่ ... ฉันแค่ดึงตัวอย่างโง่ ๆ นี้มารวมกัน ฉันจะเปลี่ยนชื่อ
Cory-G

สำหรับวิธีการนี้คุณอาจพิจารณาคลาสแทนmkDictแลมด้า ถ้าเราเรียกชั้นเรียนของเราUser"การตั้งค่า" {'st3v3': User('password','blonde','Steve Booker')}คีย์พจนานุกรมของคุณจะเป็นสิ่งที่เริ่มชอบ เมื่อ "ผู้ใช้" ของคุณอยู่ในuserตัวแปรคุณจะสามารถเข้าถึงคุณสมบัติของมันเป็นuser.hairฯลฯ
Andrew Palmer

หากคุณชอบสไตล์นี้คุณสามารถเลือกใช้collection.namedtupleได้ User = namedtuple('User', 'passwd hair name'); config = {'st3v3': User('password', 'blonde', 'Steve Booker')}
MarkM

7

การเปลี่ยนแปลงเล็กน้อยเกี่ยวกับความคิดของ Husky ที่ฉันใช้ สร้างไฟล์ชื่อ 'globals' (หรืออะไรก็ได้ที่คุณต้องการ) จากนั้นกำหนดหลายคลาสในไฟล์ดังต่อไปนี้:

#globals.py

class dbinfo :      # for database globals
    username = 'abcd'
    password = 'xyz'

class runtime :
    debug = False
    output = 'stdio'

จากนั้นหากคุณมีไฟล์รหัสสองไฟล์คือ c1.py และ c2.py ทั้งสองไฟล์สามารถมีได้ที่ด้านบน

import globals as gl

ตอนนี้โค้ดทั้งหมดสามารถเข้าถึงและตั้งค่าได้ดังนี้:

gl.runtime.debug = False
print(gl.dbinfo.username)

มีคนลืมคลาสแม้ว่าจะไม่มีการสร้างอินสแตนซ์อ็อบเจ็กต์ที่เป็นสมาชิกของคลาสนั้น และตัวแปรในคลาสที่ไม่ได้นำหน้าด้วย "self" จะใช้ร่วมกันในทุกอินสแตนซ์ของคลาสแม้ว่าจะไม่มีเลยก็ตาม เมื่อ 'debug' ถูกเปลี่ยนโดยรหัสใด ๆ รหัสอื่น ๆ ทั้งหมดจะเห็นการเปลี่ยนแปลง

เมื่อนำเข้าเป็น gl คุณสามารถมีไฟล์และตัวแปรดังกล่าวหลายไฟล์ที่ช่วยให้คุณเข้าถึงและตั้งค่าระหว่างไฟล์โค้ดฟังก์ชัน ฯลฯ แต่ไม่อันตรายจากการชนกันของเนมสเปซ

สิ่งนี้ขาดการตรวจสอบข้อผิดพลาดที่ชาญฉลาดของวิธีการอื่น ๆ แต่ง่ายและง่ายต่อการปฏิบัติตาม


1
มันได้รับการแก้ไขในการตั้งชื่อโมดูลglobalsเนื่องจากเป็นฟังก์ชันในตัวที่ส่งคืนคำสั่งพร้อมสัญลักษณ์ทุกตัวในขอบเขตส่วนกลางปัจจุบัน นอกจากนี้ PEP8 แนะนำ CamelCase (ที่มีตัวพิมพ์ใหญ่ทั้งหมดเป็นตัวย่อ) สำหรับคลาส (เช่นDBInfo) และตัวพิมพ์ใหญ่ที่มีขีดล่างสำหรับค่าคงที่ที่เรียกว่า (เช่นDEBUG)
Nuno André

1
ขอบคุณ @ NunoAndréสำหรับความคิดเห็นจนกระทั่งฉันอ่านฉันคิดว่าคำตอบนี้มีอะไรแปลก ๆglobalsผู้เขียนควรเปลี่ยนชื่อ
oglop

แนวทางนี้คือการไปของฉัน อย่างไรก็ตามฉันเห็นวิธีการมากมายที่ผู้คนกล่าวว่า "ดีที่สุด" คุณสามารถระบุข้อบกพร่องบางประการในการใช้ config.py ได้หรือไม่?
Yash Nag

5

พูดตามตรงว่าเราควรพิจารณาใช้ไลบรารีที่ดูแลPython Software Foundation :

https://docs.python.org/3/library/configparser.html

ตัวอย่างการกำหนดค่า: (รูปแบบ ini แต่มี JSON)

[DEFAULT]
ServerAliveInterval = 45
Compression = yes
CompressionLevel = 9
ForwardX11 = yes

[bitbucket.org]
User = hg

[topsecret.server.com]
Port = 50022
ForwardX11 = no

ตัวอย่างโค้ด:

>>> import configparser
>>> config = configparser.ConfigParser()
>>> config.read('example.ini')
>>> config['DEFAULT']['Compression']
'yes'
>>> config['DEFAULT'].getboolean('MyCompression', fallback=True) # get_or_else

ทำให้สามารถเข้าถึงได้ทั่วโลก:

import configpaser
class App:
 __conf = None

 @staticmethod
 def config():
  if App.__conf is None:  # Read only once, lazy.
   App.__conf = configparser.ConfigParser()
   App.__conf.read('example.ini')
  return App.__conf

if __name__ == '__main__':
 App.config()['DEFAULT']['MYSQL_PORT']
 # or, better:
 App.config().get(section='DEFAULT', option='MYSQL_PORT', fallback=3306)
 ....

ข้อเสีย:

  • ไม่สามารถควบคุมได้ไม่แน่นอนทั่วโลกรัฐ

การใช้ไฟล์. ini จะไม่มีประโยชน์หากคุณจำเป็นต้องใช้คำสั่ง if ในไฟล์อื่นของคุณเพื่อเปลี่ยนการกำหนดค่า มันจะดีกว่าถ้าใช้ config.py แทน แต่ถ้าค่าไม่เปลี่ยนและคุณแค่เรียกใช้และใช้มันฉันเห็นด้วยกับการใช้ไฟล์ of.ini
Kourosh

3

โปรดตรวจสอบระบบการกำหนดค่า IPython ซึ่งใช้งานผ่านลักษณะสำหรับการบังคับใช้ประเภทที่คุณทำด้วยตนเอง

ตัดและวางที่นี่เพื่อให้เป็นไปตามหลักเกณฑ์ SO ไม่เพียงแค่วางลิงก์เนื่องจากเนื้อหาของลิงก์เปลี่ยนแปลงไปตามกาลเวลา

เอกสารลักษณะ

นี่คือข้อกำหนดหลักที่เราต้องการให้ระบบกำหนดค่าของเรามี:

รองรับข้อมูลการกำหนดค่าตามลำดับชั้น

บูรณาการกับตัวแยกวิเคราะห์ตัวเลือกบรรทัดคำสั่ง บ่อยครั้งคุณต้องการอ่านไฟล์คอนฟิกูเรชัน แต่ลบล้างค่าบางค่าด้วยตัวเลือกบรรทัดคำสั่ง ระบบการกำหนดค่าของเราทำให้กระบวนการนี้เป็นไปโดยอัตโนมัติและอนุญาตให้ตัวเลือกบรรทัดคำสั่งแต่ละรายการเชื่อมโยงกับแอตทริบิวต์เฉพาะในลำดับชั้นการกำหนดค่าที่จะแทนที่

ไฟล์คอนฟิกูเรชันที่เป็นรหัส Python ที่ถูกต้อง สิ่งนี้สำเร็จหลายอย่าง ประการแรกเป็นไปได้ที่จะใส่ลอจิกลงในไฟล์คอนฟิกูเรชันของคุณที่ตั้งค่าแอตทริบิวต์ตามระบบปฏิบัติการของคุณการตั้งค่าเครือข่ายเวอร์ชัน Python เป็นต้นประการที่สอง Python มีไวยากรณ์ที่ง่ายมากสำหรับการเข้าถึงโครงสร้างข้อมูลแบบลำดับชั้นคือการเข้าถึงแอตทริบิวต์ปกติ (Foo. Bar.Bam.name). ประการที่สามการใช้ Python ทำให้ผู้ใช้สามารถนำเข้าแอตทริบิวต์การกำหนดค่าจากไฟล์กำหนดค่าหนึ่งไปยังอีกไฟล์หนึ่งได้ง่าย ประการที่สี่แม้ว่า Python จะพิมพ์แบบไดนามิก แต่ก็มีประเภทที่สามารถตรวจสอบได้ที่รันไทม์ ดังนั้น 1 ในไฟล์กำหนดค่าจึงเป็นจำนวนเต็ม '1' ในขณะที่ '1' เป็นสตริง

วิธีการอัตโนมัติทั้งหมดในการรับข้อมูลคอนฟิกูเรชันไปยังคลาสที่ต้องการในรันไทม์ การเขียนโค้ดที่เดินตามลำดับชั้นการกำหนดค่าเพื่อแยกแอตทริบิวต์เฉพาะเป็นเรื่องที่เจ็บปวด เมื่อคุณมีข้อมูลการกำหนดค่าที่ซับซ้อนพร้อมแอตทริบิวต์หลายร้อยรายการสิ่งนี้ทำให้คุณอยากร้องไห้

พิมพ์การตรวจสอบและการตรวจสอบความถูกต้องที่ไม่ต้องการให้ระบุลำดับชั้นการกำหนดค่าทั้งหมดแบบคงที่ก่อนรันไทม์ Python เป็นภาษาที่มีไดนามิกมากและคุณไม่เคยรู้ทุกอย่างที่ต้องกำหนดค่าเมื่อโปรแกรมเริ่มทำงาน

เพื่อให้บรรลุสิ่งนี้โดยพื้นฐานแล้วพวกเขากำหนดคลาสอ็อบเจ็กต์ 3 คลาสและความสัมพันธ์ซึ่งกันและกัน:

1) การกำหนดค่า - โดยทั่วไปคือ ChainMap / คำสั่งพื้นฐานที่มีการปรับปรุงบางอย่างสำหรับการผสาน

2) กำหนดค่าได้ - คลาสพื้นฐานสำหรับคลาสย่อยทั้งหมดที่คุณต้องการกำหนดค่า

3) แอปพลิเคชัน - อ็อบเจ็กต์ที่สร้างอินสแตนซ์เพื่อใช้งานฟังก์ชันแอปพลิเคชันเฉพาะหรือแอปพลิเคชันหลักของคุณสำหรับซอฟต์แวร์วัตถุประสงค์เดียว

ในคำพูดของพวกเขา:

ใบสมัคร: Application

แอปพลิเคชันเป็นกระบวนการที่ทำงานเฉพาะ แอปพลิเคชันที่ชัดเจนที่สุดคือโปรแกรมบรรทัดคำสั่ง ipython แต่ละแอ็พพลิเคชันอ่านไฟล์คอนฟิกูเรชันหนึ่งไฟล์หรือมากกว่าและอ็อพชันบรรทัดคำสั่งชุดเดียวจากนั้นสร้างอ็อบเจ็กต์คอนฟิกูเรชันหลักสำหรับแอ็พพลิเคชัน จากนั้นอ็อบเจ็กต์คอนฟิกูเรชันนี้จะถูกส่งผ่านไปยังอ็อบเจ็กต์ที่กำหนดค่าได้ซึ่งแอ็พพลิเคชันสร้างขึ้น อ็อบเจ็กต์ที่กำหนดค่าได้เหล่านี้ใช้ตรรกะที่แท้จริงของแอ็พพลิเคชันและรู้วิธีกำหนดค่าด้วยตัวเองเนื่องจากอ็อบเจ็กต์กำหนดค่า

แอปพลิเคชันมักจะมีแอตทริบิวต์บันทึกซึ่งเป็น Logger ที่กำหนดค่าไว้ สิ่งนี้ช่วยให้สามารถกำหนดค่าการบันทึกแบบรวมศูนย์ต่อแอปพลิเคชัน กำหนดค่าได้: กำหนดค่าได้

กำหนดค่าได้คือคลาส Python ปกติที่ทำหน้าที่เป็นคลาสพื้นฐานสำหรับคลาสหลักทั้งหมดในแอปพลิเคชัน คลาสพื้นฐานที่กำหนดค่าได้มีน้ำหนักเบาและทำสิ่งเดียวเท่านั้น

Configurable นี้เป็นคลาสย่อยของ HasTraits ที่รู้วิธีกำหนดค่าตัวเอง ลักษณะระดับคลาสที่มี metadata config = True เป็นค่าที่สามารถกำหนดค่าได้จากบรรทัดรับคำสั่งและไฟล์คอนฟิกูเรชัน

นักพัฒนาสร้างคลาสย่อยที่กำหนดค่าได้ซึ่งใช้ตรรกะทั้งหมดในแอปพลิเคชัน คลาสย่อยแต่ละคลาสเหล่านี้มีข้อมูลคอนฟิกูเรชันของตัวเองซึ่งควบคุมวิธีสร้างอินสแตนซ์

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.