从函数到当前文件的变量

时间:2019-03-11 09:48:22

标签: python python-3.x

1。摘要

我找不到如何将YAML文件中的变量添加到没有重复项的Python文件中的方法。


2。目的

我使用Pelican — static sites generatorIt use .py files for configuration。问题:

  1. I can't reuse variables from .py for JavaScript
  2. import * antipattern,甚至可以在official Pelican blog
  3. 中使用

我尝试将配置转移到YAML文件→我遇到了这个问题。


3。 MCVE

3.1。文件

"""First Python file."""
# [INFO] Using ruamel.yaml — superset of PyYAML:
# https://stackoverflow.com/a/38922434/5951529
import ruamel.yaml as yaml

SETTINGS_FILES = ["kira.yaml", "kristina.yaml"]

for setting_file in SETTINGS_FILES:
    VARIABLES = yaml.safe_load(open(setting_file))
    # [INFO] Convert Python dictionary to variables:
    # https://stackoverflow.com/a/36059129/5951529
    locals().update(VARIABLES)

# [INFO] View all variables:
# https://stackoverflow.com/a/633134/5951529
print(dir())
  • publishconf.py
"""Second Python file."""
import ruamel.yaml as yaml

# [NOTE] Another value in list
SETTINGS_FILES = ["kira.yaml", "katya.yaml"]

for setting_file in SETTINGS_FILES:
    VARIABLES = yaml.load(open(setting_file))
    locals().update(VARIABLES)


print(dir())
  • kira.yaml
DECISION: Saint Petersburg
  • kristina.yaml
SPAIN: Marbella
  • katya.yaml
BURIED: Novoshakhtinsk

3.2。预期的行为

    DECISION中的
  • SPAINmain.py变量:
$ python main.py
['DECISION', 'SETTINGS_FILES', 'SPAIN', 'VARIABLES', '__annotations__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', '__warningregistry__', 'setting_file', 'yaml']
    DECISION中的
  • BURIEDpublishconf.py变量:
$ python publishconf.py
['BURIED', 'DECISION', 'SETTINGS_FILES', 'VARIABLES', '__annotations__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', '__warningregistry__', 'setting_file', 'yaml']

3.3。问题

main.pypublishconf.py中的重复循环:

for setting_file in SETTINGS_FILES:
    VARIABLES = yaml.load(open(setting_file))
    locals().update(VARIABLES)

我不能使用重复项吗?


4。没有帮助

4.1。配置文件

"""Config Python file."""
# [INFO] Using ruamel.yaml — superset of PyYAML:
# https://stackoverflow.com/a/38922434/5951529
import ruamel.yaml as yaml

MAIN_CONFIG = ["kira.yaml", "kristina.yaml"]

PUBLISHCONF_CONFIG = ["kira.yaml", "katya.yaml"]


def kirafunction(pelicanplugins):
    """Function for both Python files."""
    for setting_file in pelicanplugins:
        # [INFO] Convert Python dictionary to variables:
        # https://stackoverflow.com/a/36059129/5951529
        variables = yaml.safe_load(open(setting_file))
        globals().update(variables)


def main_function():
    """For main.py."""
    kirafunction(MAIN_CONFIG)


def publishconf_function():
    """For publishconf.py."""
    kirafunction(PUBLISHCONF_CONFIG)
  • main.py
"""First Python file."""
import sys

from config import main_function

sys.path.append(".")


main_function()

# [INFO] View all variables:
# https://stackoverflow.com/a/633134/5951529
print(dir())
  • publishconf.py
"""Second Python file."""
import sys

from config import publishconf_function

sys.path.append(".")


publishconf_function()

print(dir())

main_functionpublishconf_function中的变量不会在文件之间共享:

$ python main.py
['__annotations__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'main_function', 'signal', 'sys']

4.2。另一个尝试

  1. 将循环包装为以下示例:

    def kirafunction():
        """Docstring."""
        for setting_file in SETTINGS_FILES:
            VARIABLES = yaml.safe_load(open(setting_file))
            locals().update(VARIABLES)
    
    
    kirafunction()
    
  2. Using global keyword

  3. I think editing locals() like that is generally a bad idea. If you think globals() is a better alternative, think it twice!

  4. Search中的
  5. Stack Overflow questions

1 个答案:

答案 0 :(得分:1)

我会避免对locals返回的内容进行任何更新,因为文档明确指出:

  

注意   该字典的内容不得修改;更改可能不会影响解释器使用的局部变量和自由变量的值。

globals函数是仅包含模块属性的字典,并且globals返回的映射确实是可写的。

因此,如果它存在于一个Python源代码中:

def kirafunction(map,settings):
  # [NOTE] Another value in list
  for setting_file in settings:
    VARIABLES = yaml.load(open(setting_file))
    map.update(VARIABLES)

导入以上函数后,可以从任何其他Python来源中使用它:

kirafunction(globals(), settings)

并将变量导入到调用模块的全局字典中。而且将是高度非Python的...

稍微有点Python化的方式是,专用于一个Python模块来保存加载yaml文件的代码新变量:

loader.py:

import ruamel.yaml as yaml

SETTINGS_FILES = ["kira.yaml", "kristina.yaml"]

for setting_file in SETTINGS_FILES:
    VARIABLES = yaml.safe_load(open(setting_file))
    # [INFO] Convert Python dictionary to variables:
    # https://stackoverflow.com/a/36059129/5951529
    globals().update(VARIABLES)

然后在您可以使用的任何其他Python模块中使用

...
import loader      # assuming that it is in sys.path...
...
print(loader.DECISION)
print(dir(loader))

但这仍然不常见,需要评论以解释其理由。


阅读您评论中的Pelican配置示例后,我假设您需要的是一种在不同脚本中导入yaml文件中声明的一堆变量的方法。在那种情况下,我会将加载变量的代码放在一个模块中,并在其他模块中更新globals()字典:

loader.py:

import ruamel.yaml as yaml

MAIN_CONFIG = ["kira.yaml", "kristina.yaml"]

PUBLISHCONF_CONFIG = ["kira.yaml", "katya.yaml"]


def kirafunction(pelicanplugins):
    """Function for both Python files."""
    variables = {}
    for setting_file in pelicanplugins:
        # [INFO] Convert Python dictionary to variables:
        # https://stackoverflow.com/a/36059129/5951529
        variables.update(yaml.safe_load(open(setting_file)))
    return variables

然后例如在publishconf.py中,您将使用:

from loader import kirafunction, PUBLISHCONF_CONFIG as pelican_config

# other Python code...

# import variables from the yaml files defined in PUBLISHCONF_CONFIG
#  because Pelican expects them as plain Python module variables
globals().update(kirafunction(pelican_config))

再次,在此用例中更新globals()可能是适当的,但通常对此不予理,,因此发表评论。