snipsco / snips-nlu

Snips Python library to extract meaning from text
https://snips-nlu.readthedocs.io
Apache License 2.0
3.89k stars 513 forks source link

Exception thrown from crf_slot_filler.py #806

Open Shotgun167 opened 5 years ago

Shotgun167 commented 5 years ago

On exit, Snips throws a few pages worth of:

2019-06-06` 10:36:19,863 [MainThread ] [VERBOSE] exit 1 Exception ignored in: <function CRFSlotFiller.del at 0x113e0b510> Traceback (most recent call last): File "/usr/local/lib/python3.7/site-packages/snips_nlu/slot_filler/crf_slot_filler.py", line 406, in del File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/pathlib.py", line 983, in new File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/pathlib.py", line 640, in _from_parts File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/pathlib.py", line 624, in _parse_args TypeError: 'NoneType' object is not callable

I stopped it by changing line 407 of "/usr/local/lib/python3.7/site-packages/snips_nlu/slot_filler/crf_slot_filler.py" to:

except (OSError, TypeError):

adrienball commented 5 years ago

@Shotgun167 Thanks for reporting this, which OS are you using ? Can you give more details about what you mean by "On exit"? It this error throwed after the python process is killed, or simply after a SnipsNLUEngine is destroyed ?

Shotgun167 commented 5 years ago

MacOS 10.13.6 Python version 3.7.0 At the end of my program I do exit(1) I don't try to deconstruct/de-initialize snips. I just exit the program.

adrienball commented 5 years ago

Do you get this error in a systematic and reproducible way? It would be great if you could provide us with some steps, and/or code, that we can follow to reproduce this issue. Thanks.

Shotgun167 commented 5 years ago

I get this error every time I my app finishes/exits. In the app, I create an object (nlp_actions.py) that does NLU for statements I give it. It creates the snips_engine in the most bog standard way:

< def init(self):

setup request using either dev or Prod

    self.snips_engine = SnipsNLUEngine.from_path("./snips/nebula_engine")

After that, I do not interact with Snips in any way other than:

< res = self.snips_engine.parse(text)

At the end of the main loop of my program, I do:

< exit(1)

I'm assuming the NoneType is because there has been some cleanup in the Python internals before Snips gets to the cleanup code in crf_slot_filler.py. I don't think it is a big deal, other than a lot of nuisance error messages, but I was getting several screens full of them and this fix made them go away.

adrienball commented 5 years ago

I cannot reproduce locally. I'm running Python3.7.3, perhaps you could try to upgrade to this version. The error is raised from pathlib internal code, which indeed could suggest that something wrong is happening when the cleanup is done after the process is killed.

adrienball commented 5 years ago

@Shotgun167 any update on this, have you tried with Python3.7.3 ? Do you run into this issue with other python versions like Python3.6 ? Thanks

Shotgun167 commented 5 years ago

I've not had time to update to 3.7.3, but we do have the problem on 3.6.  That's the version on our Jenkins server. On Thursday, July 4, 2019, 5:44:55 AM EDT, Adrien Ball notifications@github.com wrote:

@Shotgun167 any update on this, have you tried with Python3.7.3 ? Do you run into this issue with other python versions like Python3.6 ? Thanks

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or mute the thread.

adam-ra commented 5 years ago

There's still a bug in the newest version from the repo, just a different exception in del:

Exception ignored in: <bound method CRFSlotFiller.__del__ of <snips_nlu.slot_filler.crf_slot_filler.CRFSlotFiller object at 0x7f89e9058518>>
Traceback (most recent call last):
  File "/home/aradziszewski/venvs/bleeding-botf/lib/python3.6/site-packages/snips_nlu/slot_filler/crf_slot_filler.py", line 410, in __del__
  File "/home/aradziszewski/venvs/bleeding-botf/lib/python3.6/site-packages/snips_nlu/slot_filler/crf_slot_filler.py", line 407, in _cleanup
  File "/home/aradziszewski/venvs/bleeding-botf/lib/python3.6/site-packages/sklearn_crfsuite/_fileresource.py", line 37, in cleanup
TypeError: 'NoneType' object is not callable

The previous exception was:

Exception ignored in: <bound method CRFSlotFiller.__del__ of <snips_nlu.slot_filler.crf_slot_filler.CRFSlotFiller object at 0x7f8f3d9d48d0>>
Traceback (most recent call last):
  File "/home/aradziszewski/venvs/botf/lib/python3.6/site-packages/snips_nlu/slot_filler/crf_slot_filler.py", line 401, in __del__
  File "/usr/lib/python3.6/pathlib.py", line 1001, in __new__
  File "/usr/lib/python3.6/pathlib.py", line 656, in _from_parts
  File "/usr/lib/python3.6/pathlib.py", line 637, in _parse_args
TypeError: isinstance() arg 2 must be a type or tuple of types

My code reads data directly from YAML and fits the model.

        training_data_path = resources.resource_path(SNIPS_TRAIN_YAML_PATTERN.format(lang))
        training_data = snips_nlu.dataset.Dataset.from_yaml_files(lang, [training_data_path]).json
        snips_nlu_engine.fit(training_data)
adrienball commented 5 years ago

Thanks @adam-ra , I'm reopening it then. I'll try to allocate some time soon to (re)-investigate.

Essentially, the issue is that we rely on the CRFSuite C-library (wrapped in python in sklearn-crfsuite), and this lib requires a file to load a CRF model. This is annoying as we would prefer to have everything in memory, but that's how it is. So when the client code no longer needs the SnipsNLUEngine instance, we need to cleanup the CRF model files otherwise they would be left behind in temporary folders, which is not ideal. Using __del__ for such a cleanup task seemed appropriate as it doesn't require any cleanup call from the client code, but it feels like the behavior of __del__ in Python is hard to predict.

Shotgun167 commented 5 years ago

del appears to be a very iffy method to use.
https://stackoverflow.com/questions/6104535/i-dont-understand-this-python-del-behaviour

adam-ra commented 5 years ago

Thanks for explanations! I get this warning each time I run unit tests in my code; it's somehow not cropping up otherwise. BTW perhaps using pycrfsuite instead would work? I'm using this wrapper in my other code and have never had any issue or warning.


    def __init__(self, model_path):
        self.tagger = pycrfsuite.Tagger()
        self.tagger.open(model_path)

    def close(self):
        self.tagger.close()