【问题标题】:Store simple user settings in Python在 Python 中存储简单的用户设置
【发布时间】:2010-09-17 01:37:43
【问题描述】:

我正在编写一个网站,用户可以在其中进行许多设置,例如他们选择的配色方案等。我很乐意将这些设置为纯文本文件,并且安全不是问题。

我目前看到的方式是:有一个字典,其中所有的键都是用户,值是字典,其中包含用户的设置。

例如,userdb["bob"]["colour_scheme"] 的值为“blue”。

将其存储在文件中的最佳方式是什么?腌制字典?

有没有更好的方法来做我想做的事情?

【问题讨论】:

    标签: python database web settings


    【解决方案1】:

    在字典上使用cPickle 是我的选择。字典自然适合此类数据,因此鉴于您的要求,我认为没有理由不使用它们。除非您正在考虑从非 python 应用程序中读取它们,在这种情况下,您必须使用语言中立的文本格式。即使在这里,您也可以使用 pickle 和导出工具。

    【讨论】:

    • 在这种情况下,cPickle 的问题是你不能只为一个用户加载设置,你必须全部加载。 shelve 可以更好地扩展,并且使用起来同样简单。
    • 如果您的字典包含您自己的对象(不仅仅是内置对象),那么您可能会遇到麻烦。在您的代码的未来版本中,您可能会更改类名或将类移动到其他包中。这样旧数据就不会再水化到新代码中了。
    【解决方案2】:

    如果您有数据库,我可能会建议将设置存储在数据库中。但是,听起来普通文件可能更适合您的环境。

    您可能不想将所有用户设置存储在同一个文件中,因为并发访问该文件时可能会遇到问题。如果您将每个用户的设置作为字典存储在他们自己的腌制文件中,那么他们将能够独立行动。

    Pickling 是一种存储此类数据的合理方式,但不幸的是,众所周知,pickle 数据格式不适合人类阅读。您最好将其存储为repr(dictionary),这将是一种更易读的格式。要重新加载用户设置,请使用eval(open("file").read()) 或类似名称。

    【讨论】:

      【解决方案3】:

      我不解决哪个最好的问题。如果你想处理文本文件,我会考虑ConfigParser -module。另一个您可以尝试的是simplejsonyaml。你也可以考虑一个真正的数据库表。

      例如,您可以有一个名为 userattrs 的表,其中包含三列:

      • 内部用户 ID
      • 字符串属性名
      • 字符串属性值

      如果只有少数,您可以将它们存储到 cookie 中以便快速检索。

      【讨论】:

        【解决方案4】:

        这是最简单的方法。使用简单变量和import 设置文件。

        调用文件 userprefs.py

        # a user prefs file
        color = 0x010203
        font = "times new roman"
        position = ( 12, 13 )
        size = ( 640, 480 )
        

        在您的应用程序中,您需要确保可以导入此文件。你有很多个选择。

        1. 使用PYTHONPATH。要求将PYTHONPATH 设置为包含首选项文件的目录。

          一个。用于命名文件的显式命令行参数(不是最好的,但很简单)

          b.用于命名文件的环境变量。

        2. 扩展sys.path 以包含用户的主目录

        例子

        import sys
        import os
        sys.path.insert(0,os.path.expanduser("~"))
        import userprefs 
        print userprefs.color
        

        【讨论】:

        • 难道您不需要为每个用户创建一个单独的文件吗?这似乎是很多开销。
        • @Mark Biek:“这些用户将有许多设置,”对我来说,这听起来像是每个用户的设置。可能误读了问题。
        • 我投了赞成票,因为它是解决我的问题的好方法——这并不是问题所要求的。我想要一个命令行应用程序的配置文件,这是一个完全不同的用例。
        【解决方案5】:

        如果配置文件的人类可读性很重要,则可以选择the ConfigParser module,它允许您读取和写入类似.ini 的文件。但是你被限制在一个嵌套级别。

        【讨论】:

          【解决方案6】:

          如果我必须将这些设置存储在文件系统上,我会使用shelvesqlite 数据库。不过,既然您正在构建一个网站,您可能会使用某种数据库,那么为什么不直接使用它呢?

          【讨论】:

            【解决方案7】:

            您没有为此使用数据库是否有特殊原因?这似乎是正常和自然的事情 - 或者将设置的pickle存储在以用户 ID 或其他内容为键的数据库中。

            您没有描述网站的使用模式,只是考虑了一个一般网站 - 但我认为将设置保存在数据库中会比使用文件导致更少的磁盘 I/O。

            OTOH,对于客户端代码可能使用的设置,将它们作为 javascript 存储在可以缓存的静态文件中会很方便 - 代价是您可能需要在多个位置进行设置。 (我可能会将这些设置存储在数据库中,并根据需要重建静态文件)

            【讨论】:

              【解决方案8】:

              我同意关于使用 Pickled Dictionary 的回复。在 Dictionary 结构中存储简单数据非常简单有效。

              【讨论】:

                【解决方案9】:

                如果您不关心自己能够编辑文件,并且想要一种快速持久化 python 对象的方法,请使用pickle。如果您确实希望文件可以被人类读取,或被其他应用程序读取,请使用ConfigParser。如果您需要更复杂的东西,请使用某种数据库,无论是关系型 (sqlite) 还是面向对象型 (axiom, zodb)。

                【讨论】:

                  【解决方案10】:

                  对于数据库驱动的网站,当然,最好的选择是 db 表。我假设你没有做数据库的事情。

                  如果您不关心人类可读的格式,那么pickle 是一种简单直接的方法。我也听说过关于simplejson 的好报道。

                  如果人类可读性很重要,那么有两个简单的选择:

                  模块:只需使用一个模块。如果您只需要一些全局变量并且没有什么花哨的,那么这就是要走的路。如果你真的很绝望,你可以定义类和类变量来模拟部分。这里的缺点:如果文件将由用户手动编辑,错误可能难以捕捉和调试。

                  INI 格式:我一直在使用ConfigObj,取得了相当大的成功。 ConfigObj 本质上是 ConfigParser 的替代品,支持嵌套部分等等。或者,您可以定义文件的预期类型或值并对其进行验证,从而为用户/管理员提供安全网(和重要的错误反馈)。

                  【讨论】:

                    【解决方案11】:

                    我会使用 ConfigParser 模块,它会为您的示例生成一些可读性强且用户可编辑的输出:

                    [鲍勃]
                    colour_scheme:蓝色
                    英国人:是的
                    [乔]
                    color_scheme:那是“颜色”,傻!
                    英国:没有

                    下面的代码会生成上面的配置文件,然后打印出来:

                    import sys
                    from ConfigParser import *
                    
                    c = ConfigParser()
                    
                    c.add_section("bob")
                    c.set("bob", "colour_scheme", "blue")
                    c.set("bob", "british", str(True))
                    
                    c.add_section("joe")
                    c.set("joe", "color_scheme", "that's 'color', silly!")
                    c.set("joe", "british", str(False))
                    
                    c.write(sys.stdout)  # this outputs the configuration to stdout
                                         # you could put a file-handle here instead
                    
                    for section in c.sections(): # this is how you read the options back in
                        print section
                        for option in c.options(section):
                                print "\t", option, "=", c.get(section, option)
                    
                    print c.get("bob", "british") # To access the "british" attribute for bob directly
                    

                    请注意,ConfigParser 仅支持字符串,因此您必须像我在上面对布尔值所做的那样进行转换。请参阅effbot 了解基础知识。

                    【讨论】:

                      【解决方案12】:

                      内置的sqlite3 模块可能比大多数替代品要简单得多,并且可以让您随时准备更新到完整的 RDBMS。

                      【讨论】:

                        猜你喜欢
                        • 1970-01-01
                        • 2012-07-29
                        • 1970-01-01
                        • 1970-01-01
                        • 2010-10-26
                        • 2020-05-19
                        • 2022-01-20
                        • 1970-01-01
                        • 2015-11-24
                        相关资源
                        最近更新 更多