添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

I want to check if a product ID exists in a file. I came up with following python script:

#!/usr/bin/python
import os
import java.io
flowFile = session.get()
exists = False
if (flowFile != None):
    if !os.path.exists('/home/nifi/products.csv'):
        session.transfer(flowFile, REL_SUCCESS)
    else:
        asin = flowFile.getAttribute('asin')
        with open('/home/nifi/products.csv') as csv:
            if asin in csv.read():
                exists = True
                session.transfer(flowFile, REL_FAILURE)
    if !exists:
        session.transfer(flowFile, REL_SUCCESS)

However I am getting an error which I find really hard to interpret. It basically just says javax.script.ScriptException: NameError: name 's' is not defined in <script> at line number 9 Any ideas whats causing this?

2018-11-05 19:27:29,267 ERROR [Timer-Driven Process Thread-2] o.a.nifi.processors.script.ExecuteScript ExecuteScript[id=e52f46d5-0166-1000-fc42-8e9565527c21] Failed to process session due to org.apache.nifi.processor.exception.ProcessException: javax.script.ScriptException: NameError: name 's' is not defined in <script> at line number 9: org.apache.nifi.processor.exception.ProcessException: javax.script.ScriptException: NameError: name 's' is not defined in <script> at line number 9
org.apache.nifi.processor.exception.ProcessException: javax.script.ScriptException: NameError: name 's' is not defined in <script> at line number 9
 at org.apache.nifi.processors.script.ExecuteScript.onTrigger(ExecuteScript.java:239)
 at org.apache.nifi.controller.StandardProcessorNode.onTrigger(StandardProcessorNode.java:1165)
 at org.apache.nifi.controller.tasks.ConnectableTask.invoke(ConnectableTask.java:203)
 at org.apache.nifi.controller.scheduling.TimerDrivenSchedulingAgent$1.run(TimerDrivenSchedulingAgent.java:117)
 at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
 at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308)
 at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180)
 at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294)
 at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
 at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
 at java.lang.Thread.run(Thread.java:748)
Caused by: javax.script.ScriptException: NameError: name 's' is not defined in <script> at line number 9
 at org.python.jsr223.PyScriptEngine.scriptException(PyScriptEngine.java:222)
 at org.python.jsr223.PyScriptEngine.eval(PyScriptEngine.java:59)
 at org.python.jsr223.PyScriptEngine.eval(PyScriptEngine.java:31)
 at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:264)
 at org.apache.nifi.script.impl.JythonScriptEngineConfigurator.eval(JythonScriptEngineConfigurator.java:59)
 at org.apache.nifi.processors.script.ExecuteScript.onTrigger(ExecuteScript.java:229)
 ... 10 common frames omitted
Caused by: org.python.core.PyException: null
 at org.python.core.Py.NameError(Py.java:290)
 at org.python.core.PyFrame.getname(PyFrame.java:257)
 at org.python.pycode._pyx189507.f$0(<script>:18)
 at org.python.pycode._pyx189507.call_function(<script>)
 at org.python.core.PyTableCode.call(PyTableCode.java:171)
 at org.python.core.PyCode.call(PyCode.java:18)
 at org.python.core.Py.runCode(Py.java:1614)
 at org.python.core.__builtin__.eval(__builtin__.java:497)
 at org.python.core.__builtin__.eval(__builtin__.java:501)
 at org.python.util.PythonInterpreter.eval(PythonInterpreter.java:259)
 at org.python.jsr223.PyScriptEngine.eval(PyScriptEngine.java:57)
 ... 14 common frames omitted
						

That error message is misleading, Jython doesn't put the "real" error message in the getMessage() method of its exception(s), see this issue. You've got a couple things going on here, the first is that you can't use the bang character (!) for a boolean NOT, instead you should use "not". After that, if the file doesn't exist, it will be transferred to REL_SUCCESS in your first "if" statement, and then since "exists" is never set to True, then it will try to transfer the same flow file again. Even though they're the same relationship, the framework notes that a flow file has already been marked for transfer, and will complain if it is transferred again (even to the same relationship), as this identifies a logic bug.

I'm not exactly following what you're trying to do here, please feel free to elaborate and I can help out getting you where you need to go.

So along the flow I have an attribute, which is called asin (aka product ID). The flow should fail when an ID already exists in a local csv file. With your help I changed my code to

#!/usr/bin/python
import os
import java.io
flowFile = session.get()
productFound = False
if (flowFile != None):
    if os.path.exists('/home/nifi/products.csv'):
        asin = flowFile.getAttribute('asin')
        with open('/home/nifi/products.csv') as csv:
            if asin in csv.read():
                productFound = True
    if productFound:
        session.transfer(flowFile, REL_FAILURE)
    else:
        session.transfer(flowFile, REL_SUCCESS)

I falsely assumed that I could call REL_FAILURE/SUCCESS multiple times.

Apache Hadoop and associated open source project names are trademarks of the Apache Software Foundation. For a complete list of trademarks, click here.