Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/349.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何在较长的非json文本中检测和缩进json子字符串?_Python_Json_Indentation_Pretty Print - Fatal编程技术网

Python 如何在较长的非json文本中检测和缩进json子字符串?

Python 如何在较长的非json文本中检测和缩进json子字符串?,python,json,indentation,pretty-print,Python,Json,Indentation,Pretty Print,我有一个现有的Python应用程序,其日志如下: import logging import json logger = logging.getLogger() some_var = 'abc' data = { 1: 2, 'blah': { ['hello'] } } logger.info(f"The value of some_var is {some_var} and data is {json.dumps(data)}") 因此给出了logger.

我有一个现有的Python应用程序,其日志如下:

import logging
import json
logger = logging.getLogger()

some_var = 'abc'
data = {
   1: 2,
   'blah': {
      ['hello']
   }
}

logger.info(f"The value of some_var is {some_var} and data is {json.dumps(data)}")
因此给出了
logger.info
函数:

The value of some_var is abc and data is {1: 2,"blah": {["hello"]}}
目前,我的日志转到AWS CloudWatch,它有一些魔力,并以缩进的方式呈现如下:

The value of some_var is abc and data is {
   1: 2,
   "blah": {
      ["hello"]
   }
}
这使得日志非常清晰易读

现在,我想对我的日志进行一些更改,用另一个python脚本自己处理它,该脚本围绕我的代码,并在出现故障时通过电子邮件发送日志

我想要的是以某种方式获取每个日志条目(或条目流/列表),并应用此缩进

所以我想要一个函数,它接收一个字符串,并检测该字符串的哪些子集是json,然后插入
\n
以漂亮地打印该json

输入示例:

您好,{“a”:{“b”:“c”}是一些json数据,但{“c”:[1,2,3]}也是

示例输出

Hello, 
{
  "a": {
    "b": "c"
  }
} 
is some json data, but also 
{
  "c": [
    1,
    2,
    3
  ]
}
is too
我已经考虑过将每个条目分成第一个
{
前后的所有内容。左半部分保持原样,右半部分传递给
json.dumps(json.loads(x),indent=4)

但是如果日志文件中json对象后面有东西呢? 好的,我们可以选择第一个
{
之后和最后一个
}
之前的所有内容。 然后将中间的位传递给JSON库

但是,如果此日志条目中有两个JSON对象(如上面的示例中),我们将必须使用堆栈来确定在所有先前的
{
都用相应的
}
关闭之后是否会出现任何
{

但是如果有类似于
{“a”:“\}”}
.Hmm的东西,我们需要处理转义。 现在我发现自己必须从头开始编写一个完整的json解析器

有什么简单的方法可以做到这一点吗

我想我可以使用正则表达式将整个repo中的
json.dumps(x)
的每个实例替换为
json.dumps(x,indent=4)
。但是
json.dumps
有时在日志语句之外使用,它只会使我所有的日志行都额外长一点。有一个简洁优雅的解决方案吗


(如果它能够解析和缩进python中
str(x)
生成的类似json的输出,则会获得额外的积分。这基本上是带有单引号而不是双引号的json。)

要从字符串中提取json对象,请参阅该答案中的函数将处理JSON对象和嵌套的JSON对象,但不处理其他对象。如果您的日志中有JSON对象之外的列表,则不会获取该列表

在您的情况下,修改函数以同时返回所有JSON对象周围的字符串/文本,以便您可以将它们一起放入日志(或替换日志行):

使用该函数处理日志行,将它们添加到字符串列表中,然后将这些字符串组合在一起,为输出、记录器等生成单个字符串:

def jsonify_logline(line):
    line_parts = []
    for result in extract_json_objects(line):
        if isinstance(result, dict):  # got a JSON obj
            line_parts.append(json.dumps(result, indent=4))
        else:                         # got text/non-JSON-obj
            line_parts.append(result)
    # (don't make that a list comprehension, quite un-readable)

    return ''.join(line_parts)
例如:

>>> demo_text = """Hello, {"a": {"b": "c"}} is some json data, but also {"c": [1,2,3]} is too"""
>>> print(jsonify_logline(demo_text))
Hello, {
    "a": {
        "b": "c"
    }
} is some json data, but also {
    "c": [
        1,
        2,
        3
    ]
} is too
>>>

其他与本会有所帮助的非直接相关事项:

  • 不要对所有日志行使用
    json.dumps(x)
    ,而是按照创建一个类似
    logdump(x)
    的函数,该函数可以执行您想要执行的任何操作,如
    json.dumps(x)
    ,或
    json.dumps(x,indent=4)
    ,或
    jsonify\u日志行(x)
    。这样,如果需要更改所有日志的JSON格式,只需更改一个函数即可;无需大量“搜索和替换”,这会带来自身的问题和边缘情况。
    • 您甚至可以向它添加一个可选参数
      pretty=True
      ,以决定是否要缩进
  • 您可以批量搜索并替换所有现有的日志行来执行
    logger.blah(jsonify_logline())
  • 如果您是JSON转储自定义对象/类实例,那么请使用它们的方法始终输出打印精美的JSON,并且输出的是非精美/紧凑的。
    • 然后您就不需要修改日志行了。执行
      logger.info(f'hereismyobject{x}')
      将直接调用
      obj.\uuu str\uuu

太好了!像这样的
logdump
函数会很好。特别是我有一个函数,有时我想将包含日期时间的dict转储到json(这会导致
json.dumps
崩溃)
jsonify_logline
是您的新
logdump
。它不应该为datetimes提供错误,因为它不是dict/json对象。但也可以将其包装在try else块中。更新:修复了一个错误,即最后一个json对象之后的尾随文本不会返回。
>>> demo_text = """Hello, {"a": {"b": "c"}} is some json data, but also {"c": [1,2,3]} is too"""
>>> print(jsonify_logline(demo_text))
Hello, {
    "a": {
        "b": "c"
    }
} is some json data, but also {
    "c": [
        1,
        2,
        3
    ]
} is too
>>>