使用其他文件的内容预处理(填充、生成)文件
Preprocess (populate, generate) files with the content of other files
我将使用一个有代表性的例子来解释我的问题所在。
假设我有这两个配置文件:
# product-conf.file
seo_title: general_title
seo_description: seo_description
seo_canonical: seo_canonical
product_id: general_id
title: general_title
intro: general_intro
.
# service-conf.file
seo_title: general_title
seo_description: seo_description
seo_canonical: seo_canonical
service_id: general_id
title: general_title
products: list_products
如您所见,前3行(配置字段)完全相同。我实际上正在为这些文件使用 YAML。我想在可维护文件中包含一些代码并将它们包含在调用中。我需要一个预处理器来处理这些。类似于:
# snippet-seo.file
seo_title: general_title
seo_description: seo_description
seo_canonical: seo_canonical
.
# product-conf-master.file
@include snippet-seo
product_id: general_id
title: general_title
intro: general_intro
.
# service-conf-master.file
@include snippet-seo
service_id: general_id
title: general_title
products: list_products
预处理器将读取 /masters/*
中的所有主文件,参与所有调用并将它们替换为 /snippets/
中的适当片段并将结果保存在 /
我正在使用 @
进行调用,但我可以选择适合所选预处理器的任何其他格式。我使用这种方式是因为它非常类似于 SASS 指令 @extend
或 @include
.
实现此目标的最佳和最简单方法是什么?节点包将是我的第一选择。
如果您不一定需要预处理文件,您可以使用小型 YAML 处理程序解决此问题(您可以使用一些基于节点的编程来完成此操作)。
import pathlib
import ruamel.yaml
yaml = ruamel.yaml.YAML()
master = pathlib.Path('master.file')
data = yaml.load(master))
common = data['common']
for file_name in data:
if file_name == 'common':
continue
data_out = ruamel.yaml.comments.CommentedMap()
# you can leave out the following two lines of code if you do a safe_load()
# but you will lose the ordering in your output file
for k, v in common.items():
data_out[k] = v
for k, v in data[file_name].items():
data_out[k] = v
with open(file_name, 'wb') as fp:
yaml.dump(data_out, stream=fp)
给定文件 master.file
中的以下输入:
# YAML master file
common: &COMMON
seo_title: general_title
seo_description: seo_description
seo_canonical: seo_canonical
product-conf.file:
<<: *COMMON
product_id: general_id
title: general_title
intro: general_intro
service-conf.file:
<<: *COMMON
service_id: general_id
title: general_title
products: list_products
运行 程序给你两个文件,product-conf.file
::
seo_title: general_title
seo_description: seo_description
seo_canonical: seo_canonical
product_id: general_id
title: general_title
intro: general_intro
和service-conf.file
:
seo_title: general_title
seo_description: seo_description
seo_canonical: seo_canonical
service_id: general_id
title: general_title
products: list_products
也可以将这三个部分放在单独的输入文件中,而不是将值放在一个组合文件中。
或者,如果您的实际输入文件不包含任何由 cpp
以特殊方式处理的内容,您可以这样做:
cpp -P -include master.in -o service-conf.file service-conf.in
与 master.in
:
seo_title: general_title
seo_description: seo_description
seo_canonical: seo_canonical
和service-conf.in
:
service_id: general_id
title: general_title
products: list_products
这给出了与前面示例相同的 service-conf.out
。 product-conf.in
当然会以同样的方式工作。
cpp
的 -P
选项抑制调试输出注释,-include
包含参数,就好像输入文件的第一行有预处理程序指令一样:
#include "master.in"
您也可以明确说明并省略命令行选项。
我将使用一个有代表性的例子来解释我的问题所在。
假设我有这两个配置文件:
# product-conf.file
seo_title: general_title
seo_description: seo_description
seo_canonical: seo_canonical
product_id: general_id
title: general_title
intro: general_intro
.
# service-conf.file
seo_title: general_title
seo_description: seo_description
seo_canonical: seo_canonical
service_id: general_id
title: general_title
products: list_products
如您所见,前3行(配置字段)完全相同。我实际上正在为这些文件使用 YAML。我想在可维护文件中包含一些代码并将它们包含在调用中。我需要一个预处理器来处理这些。类似于:
# snippet-seo.file
seo_title: general_title
seo_description: seo_description
seo_canonical: seo_canonical
.
# product-conf-master.file
@include snippet-seo
product_id: general_id
title: general_title
intro: general_intro
.
# service-conf-master.file
@include snippet-seo
service_id: general_id
title: general_title
products: list_products
预处理器将读取 /masters/*
中的所有主文件,参与所有调用并将它们替换为 /snippets/
中的适当片段并将结果保存在 /
我正在使用 @
进行调用,但我可以选择适合所选预处理器的任何其他格式。我使用这种方式是因为它非常类似于 SASS 指令 @extend
或 @include
.
实现此目标的最佳和最简单方法是什么?节点包将是我的第一选择。
如果您不一定需要预处理文件,您可以使用小型 YAML 处理程序解决此问题(您可以使用一些基于节点的编程来完成此操作)。
import pathlib
import ruamel.yaml
yaml = ruamel.yaml.YAML()
master = pathlib.Path('master.file')
data = yaml.load(master))
common = data['common']
for file_name in data:
if file_name == 'common':
continue
data_out = ruamel.yaml.comments.CommentedMap()
# you can leave out the following two lines of code if you do a safe_load()
# but you will lose the ordering in your output file
for k, v in common.items():
data_out[k] = v
for k, v in data[file_name].items():
data_out[k] = v
with open(file_name, 'wb') as fp:
yaml.dump(data_out, stream=fp)
给定文件 master.file
中的以下输入:
# YAML master file
common: &COMMON
seo_title: general_title
seo_description: seo_description
seo_canonical: seo_canonical
product-conf.file:
<<: *COMMON
product_id: general_id
title: general_title
intro: general_intro
service-conf.file:
<<: *COMMON
service_id: general_id
title: general_title
products: list_products
运行 程序给你两个文件,product-conf.file
::
seo_title: general_title
seo_description: seo_description
seo_canonical: seo_canonical
product_id: general_id
title: general_title
intro: general_intro
和service-conf.file
:
seo_title: general_title
seo_description: seo_description
seo_canonical: seo_canonical
service_id: general_id
title: general_title
products: list_products
也可以将这三个部分放在单独的输入文件中,而不是将值放在一个组合文件中。
或者,如果您的实际输入文件不包含任何由 cpp
以特殊方式处理的内容,您可以这样做:
cpp -P -include master.in -o service-conf.file service-conf.in
与 master.in
:
seo_title: general_title
seo_description: seo_description
seo_canonical: seo_canonical
和service-conf.in
:
service_id: general_id
title: general_title
products: list_products
这给出了与前面示例相同的 service-conf.out
。 product-conf.in
当然会以同样的方式工作。
cpp
的 -P
选项抑制调试输出注释,-include
包含参数,就好像输入文件的第一行有预处理程序指令一样:
#include "master.in"
您也可以明确说明并省略命令行选项。