【问题标题】:How to pass a parameter to python script in Nifi如何在Nifi中将参数传递给python脚本
【发布时间】:2023-03-14 04:40:02
【问题描述】:

也许这是一个愚蠢的问题,但我不得不问。

我在 Nifi 中有一个 Collect_data 处理器,它将消息流式传输到另一个进程,该进程使用 python 脚本来解析并创建 json 文件。问题是我不知道 python 脚本中函数的输入是什么。如何将这些消息(16 位数字)从 Collect_data 处理器传递到下一个处理器包含 python 脚本。有什么好的,基本的例子吗?

我已经在网上找了一些例子,但不是很明白。

import datetime
import hashlib
from urlparse import urlparse, parse_qs
import sys
from urlparse import urlparse, parse_qs
from datetime import *
import json
import java.io
from org.apache.commons.io import IOUtils
from java.nio.charset import StandardCharsets
from org.apache.nifi.processor.io import StreamCallback
from time import time


def parse_zap(inputStream, outputStream):
    data = inputStream
    buf = (hashlib.sha256(bytearray.fromhex(data)).hexdigest())
    buf = int(buf, 16)
    buf_check = str(buf)
    if buf_check[17] == 2:
        pass
    datetime_now = datetime.now()
    log_date = datetime_now.isoformat()
    try:
        mac = buf_check[7:14].upper()
        ams_id = buf_check[8:]
        action = buf_check[3:4]
        time_a = int(time())
        dict_test = {
        "user": {
            "guruq" : 'false'
        },
        "device" : {
            "type" : "siolbox",
            "mac": mac
        },
        "event" : {
            "origin" : "iptv",
            "timestamp": time_a,
            "type": "zap",
            "product-type" : "tv-channel",
            "channel": {
                "id" : 'channel_id',
                "ams-id": ams_id
            },
            "content": {
                "action": action
            }
        }
        }
        return dict_test
    except Exception as e:
        print('%s nod PARSE 500 \"%s\"' % (log_date, e))

感谢我没看错,但现在我无法创建输出。 提前致谢。

【问题讨论】:

    标签: python arguments apache-nifi


    【解决方案1】:

    看看这个脚本:

    import json
    import java.io
    from org.apache.commons.io import IOUtils
    from java.nio.charset import StandardCharsets
    from org.apache.nifi.processor.io import StreamCallback
    
    class PyStreamCallback(StreamCallback):
      def __init__(self):
            pass
      def process(self, inputStream, outputStream):
        text = IOUtils.readLines(inputStream, StandardCharsets.UTF_8)
        for line in text[1:]:
            outputStream.write(line + "\n") 
    
    flowFile = session.get()
    if (flowFile != None):
      flowFile = session.write(flowFile,PyStreamCallback())
      flowFile = session.putAttribute(flowFile, "filename", flowFile.getAttribute('filename').split('.')[0]+'_translated.json')
      session.transfer(flowFile, REL_SUCCESS)
    

    它从一个属性中获取要从流文件中删除的行数,然后获取流文件并在没有这些行的情况下再次编写它,这很简单,也是一个很好的例子,如何使用属性,以及如何使用流文件。

    根据您更新的代码,您的代码必须如下所示:

    import datetime
    import hashlib
    from urlparse import urlparse, parse_qs
    import sys
    from urlparse import urlparse, parse_qs
    from datetime import *
    import json
    import java.io
    from org.apache.commons.io import IOUtils
    from java.nio.charset import StandardCharsets
    from org.apache.nifi.processor.io import StreamCallback
    from time import time
    
    
    class PyStreamCallback(StreamCallback):
      def __init__(self):
            pass
      def process(self, inputStream, outputStream):
        data = inputStream
        buf = (hashlib.sha256(bytearray.fromhex(data)).hexdigest())
        buf = int(buf, 16)
        buf_check = str(buf)
        if buf_check[17] == 2:
            pass
        datetime_now = datetime.now()
        log_date = datetime_now.isoformat()
        try:
            mac = buf_check[7:14].upper()
            ams_id = buf_check[8:]
            action = buf_check[3:4]
            time_a = int(time())
            dict_test = {
            "user": {
                "guruq" : 'false'
            },
            "device" : {
                "type" : "siolbox",
                "mac": mac
            },
            "event" : {
                "origin" : "iptv",
                "timestamp": time_a,
                "type": "zap",
                "product-type" : "tv-channel",
                "channel": {
                    "id" : 'channel_id',
                    "ams-id": ams_id
                },
                "content": {
                    "action": action
                }
            }
            }
            return dict_test
        except Exception as e:
            print('%s nod PARSE 500 \"%s\"' % (log_date, e))
    
    flowFile = session.get()
    if (flowFile != None):
      flowFile = session.write(flowFile,PyStreamCallback())
      flowFile = session.putAttribute(flowFile, "filename", flowFile.getAttribute('filename').split('.')[0]+'_translated.json')
      session.transfer(flowFile, REL_SUCCESS)        
    

    【讨论】:

    • 我已经用 Nifi 窗口中使用的 python 脚本的代码更新了我的问题。不确定我是否需要创建类并将函数放入其中?基于我的代码的任何直接提示都会非常有帮助。顺便说一句,谢谢你:)
    【解决方案2】:

    我想我理解你的问题,但你的流程有点模棱两可。我正在回答几种不同的可能情况。

    1. 您有一个处理器,它从源(即FetchFTP)获取数据,并连接到一个ExecuteScript 处理器,其中包含一个用于转换这些值的 Python 脚本。在这种情况下,Python 脚本可以直接使用标准 API 对流文件属性和内容进行操作。有关编写自定义脚本以对数据进行操作的许多示例,请参阅Matt Burgess' blog
    2. 您有一个处理器,它从源获取数据并连接到ExecuteStreamCommand 处理器,该处理器使用python my_external_script.py arg1 arg2 ... 之类的命令调用外部Python 脚本。在这种情况下,流文件内容由ExecuteStreamCommand 处理器传递给STDIN,因此您的脚本应该以这种方式使用它。 This answer explains 更多关于在 Python 脚本中使用 ExecuteStreamCommand 的信息。
    3. 您有一个自定义处理器,它在内部调用一个单独的 Python 进程。这是一个坏主意,应该重构为其他模型之一。这打破了关注点的分离,失去了处理器生命周期的帮助,模糊了线程处理和计时,缺乏出处可见性,并且违背了 NiFi 的开发模型。

    如果您的 Python 脚本非常简单,您可以将其放在 ScriptedRecordWriter 中并使用它同时处理多个“记录”以获得性能优势。这可能会针对您的用例进行改进,具体取决于您的流程和传入数据的样子。

    2018-10-03 10:50更新

    尝试在ExecuteScript 正文中使用此脚本:

    import json
    import java.io
    from org.apache.commons.io import IOUtils
    from java.nio.charset import StandardCharsets
    from org.apache.nifi.processor.io import StreamCallback
    
    class PyStreamCallback(StreamCallback):
        def __init__(self):
            pass
        def process(self, inputStream, outputStream):
            text = IOUtils.toString(inputStream, StandardCharsets.UTF_8)
            result = parse_zap(text)
    
            outputStream.write(bytearray(result.encode('utf-8')))
    
    flowFile = session.get()
    if (flowFile != None):
        flowFile = session.write(flowFile,PyStreamCallback())
        flowFile = session.putAttribute(flowFile, "parsed_zap", "true")
        session.transfer(flowFile, REL_SUCCESS)
    
    // Your parse_zap() method here, with the signature changed to just accept a single string
    ...
    

    【讨论】:

    • 首先,非常感谢您的帮助。但我仍然没有得到。我必须为此创建课程吗?我已经用我在 Nifi 处理器窗口中使用的 python 脚本更新了我的问题,你能给我一些直接的提示吗?
    猜你喜欢
    • 1970-01-01
    • 2010-10-26
    • 1970-01-01
    • 1970-01-01
    • 2012-08-23
    • 1970-01-01
    • 1970-01-01
    • 2016-09-02
    • 2012-12-29
    相关资源
    最近更新 更多