Skip to main content

I'm using a PythonCaller to get a list of files in an FTP site folder as per this question:

https://knowledge.safe.com/questions/35179/use-pythoncaller-to-get-list-of-files-in-directory.html

This is because at the time, the FTPCaller didn't have the ability to download a folder, and the names of the files I want to download are not known. Once the list of files has been retrieved, the names of those that are CSV files are passed to the FTPCaller to download.

The FTP download functionality is in its own Workspace, called from a parent Workspace by a WorkspaceRunner. If there is a problem with the FTPCaller (Rejected port), an email is sent and a Terminator terminates the Workspace. The parent Workspace then picks this up via the Failed port of the WorkspaceRunner and abort subsequent processing steps that would have taken place on the downloaded data.

It also used to send an email and terminate if there are no files to download, or none of the files are CSVs. I now want to Terminate the Workspace and subsequent processing in parent Workspace but not send any emails. I have added a second Terminator to the FTP Workspace with the custom message "No CSV files to download from FTP site". The parent Workspace has a Tester attached to the Failed port of the WorkspaceRunner, and if this is the failure message, does not send the error alert email.

This works fine if there are some files, but none are CSVs, but if there are no files at all, I get this after the Terminator has fired:

2019-04-25 13:30:09| 1.3| 0.0|WARN |

 

2019-04-25 13:30:09| 1.3| 0.0|ERROR |Error encountered while calling method `input'

 

2019-04-25 13:30:09| 1.3| 0.0|FATAL |PythonCaller(PythonFactory): PythonFactory failed to process feature

 

2019-04-25 13:30:09| 1.3| 0.0|ERROR |A fatal error has occurred. Check the logfile above for details

Is this because the Terminator is firing too early? Is it not giving the PythonCaller time to finish? This seems to be the case because if I add a FeatureHolder before the Terminator, I don't get the fatal error.

This is slightly by the way, because the custom Termination message is not getting passed back to the WorkspaceRunner as I thought it would. I guess it only gets written to the log...? If so, is there a way of feeding back custom messages to the WorkspaceRunner so I can test them and act accordingly?

Hi @tim_wood

I'm not certain I'm understanding what you have described correctly. But based on my understanding of your Python script, no features will be output from the PythonCaller if there are no files? Is this correct?


Hi @tim_wood

I'm not certain I'm understanding what you have described correctly. But based on my understanding of your Python script, no features will be output from the PythonCaller if there are no files? Is this correct?

Hi @debbiatsafe that's correct. For clarity, these are the possible scenarios for FTP...

1) There are CSV files beginning with "JobExport-": These should be downloaded.

2) There are CSV files but they have different names: These will be filtered out by a Tester. Then the NOINPUT port of a NoFeaturesTester will trigger the Terminator with the message "No CSV files to download from FTP site".

3) A mix of CSV files i.e. a combination of 1) and 2), or CSV files matching 1) and non-CSV files. The CSV files matching 1) should be downloaded. No Terminator will be triggered.

4) No files at all, or only non-CSV files: Testers will filter out anything that is not a CSV file and doesn't have a file name beginning with "JobExport". Then the NOINPUT port of a NoFeaturesTester will trigger the Terminator with the message "No CSV files to download from FTP site".


Hi @tim_wood

Can you post the logfile regarding the python error, because it could just be an error in the python that is causing that warning.

Cheers


Hi @debbiatsafe that's correct. For clarity, these are the possible scenarios for FTP...

1) There are CSV files beginning with "JobExport-": These should be downloaded.

2) There are CSV files but they have different names: These will be filtered out by a Tester. Then the NOINPUT port of a NoFeaturesTester will trigger the Terminator with the message "No CSV files to download from FTP site".

3) A mix of CSV files i.e. a combination of 1) and 2), or CSV files matching 1) and non-CSV files. The CSV files matching 1) should be downloaded. No Terminator will be triggered.

4) No files at all, or only non-CSV files: Testers will filter out anything that is not a CSV file and doesn't have a file name beginning with "JobExport". Then the NOINPUT port of a NoFeaturesTester will trigger the Terminator with the message "No CSV files to download from FTP site".

Hi @tim_wood

Would you be able to post a simplified version of your workspaces (both parent and child)? That would be greatly appreciated. If not possible, a screenshot of your workspaces would be helpful.

In addition, I was able to see the Termination message (from the Terminator) in the _failure_message attribute that is output from the Failed port of the workspace runner in FME 2019.

 


Hi @tim_wood

Would you be able to post a simplified version of your workspaces (both parent and child)? That would be greatly appreciated. If not possible, a screenshot of your workspaces would be helpful.

In addition, I was able to see the Termination message (from the Terminator) in the _failure_message attribute that is output from the Failed port of the workspace runner in FME 2019.

 

Hi @debbiatsafe here's a redacted version the FTP Workspace and a screenshot of the relevant section from the parent Workspace.

DownloadCSVsFromFTP - for FME QnA.fmw

Update - Tester properties (I've tried with and without double quotes):


Hi @debbiatsafe here's a redacted version the FTP Workspace and a screenshot of the relevant section from the parent Workspace.

DownloadCSVsFromFTP - for FME QnA.fmw

Update - Tester properties (I've tried with and without double quotes):

Thank you for providing a workspace. I believe you are seeing the error because the Terminator runs while the PythonCaller's PythonFactory is still in the process of shutting down.

As the Terminator immediately shuts down the translation, the PythonFactory is not able to shut down cleanly and this error is shown. Note: the Emailer also shows a similar error (eg. PythonFactory failed to process feature).

As for getting the _failure_message, I would recommend using the LIKE operator instead of EQUAL (=). If you inspect this attribute, you will see it contains the entirety of the child workspace log file (including the Termination message).

I hope this information helps.
Thank you for providing a workspace. I believe you are seeing the error because the Terminator runs while the PythonCaller's PythonFactory is still in the process of shutting down.

As the Terminator immediately shuts down the translation, the PythonFactory is not able to shut down cleanly and this error is shown. Note: the Emailer also shows a similar error (eg. PythonFactory failed to process feature).

As for getting the _failure_message, I would recommend using the LIKE operator instead of EQUAL (=). If you inspect this attribute, you will see it contains the entirety of the child workspace log file (including the Termination message).

I hope this information helps.

Thanks @debbiatsafe that makes sense. So using the FeatureHolder allows the PythonCaller to shut down cleanly. I think I also need to re-work the section with the NoFeaturesTester because if there are no files at all on the FTP server, you end up with two features being produced - one from the PythonCaller output, and one from the NoFeaturesTester. The NoFeaturesTester feature reaches Terminator_2 first and stops the feature coming out of the FeatureHolder, but I will still try and fix it as it's bothering me! I think the solution is to remove the NoFeaturesTester and connect the Failed port of the preceding Tester to Terminator_2. I'll be back with an update on how this has all worked out later. Hasta la vista, broken Workspace!


Thank you for providing a workspace. I believe you are seeing the error because the Terminator runs while the PythonCaller's PythonFactory is still in the process of shutting down.

As the Terminator immediately shuts down the translation, the PythonFactory is not able to shut down cleanly and this error is shown. Note: the Emailer also shows a similar error (eg. PythonFactory failed to process feature).

As for getting the _failure_message, I would recommend using the LIKE operator instead of EQUAL (=). If you inspect this attribute, you will see it contains the entirety of the child workspace log file (including the Termination message).

I hope this information helps.

Yes I think that's sorted it. The Passed port of Tester_2 now goes to a FeatureHolder before Terminator_2 to allow the PythonCaller to shut down. The Failed port of Tester_2 goes to Tester, and the Failed port of that goes to an Aggregator (attributes only) before going to Terminator_2. This may be strictly unnecessary, but it ensures that only one feature goes to Terminator_2 if there is more than one rogue file on the FTP site. Any vaild CSV files go from the Passed port of Tester to be downloaded.

In the parent Workspace, I've changed the = in the Tester to Contains which now correctly picks up the Termination message :-)


Hi @tim_wood

Would you be able to post a simplified version of your workspaces (both parent and child)? That would be greatly appreciated. If not possible, a screenshot of your workspaces would be helpful.

In addition, I was able to see the Termination message (from the Terminator) in the _failure_message attribute that is output from the Failed port of the workspace runner in FME 2019.

 

Hi @debbiatsafe

I just ran into a similar situation. It's quite easy to reproduce.

See the attached workspace.terminatorafterpyhtoncaller.fmw


Hi @debbiatsafe

I just ran into a similar situation. It's quite easy to reproduce.

See the attached workspace.terminatorafterpyhtoncaller.fmw

Hi @mirco

As mentioned in this earlier comment, this error will occur when a PythonFactory is not shut down cleanly, as will be the case when a Terminator is used directly after a PythonCaller.


Hi @mirco

As mentioned in this earlier comment, this error will occur when a PythonFactory is not shut down cleanly, as will be the case when a Terminator is used directly after a PythonCaller.

D'oh sorry for not reading carefully. But I played a little bit around with this scenario, and it seems that the key point is using a blocking transformer between the PythonCaller and the Terminator. You can put a large number of non-blocking transformer between the PythonCaller and the Terminator and you will get always the FATAL, but not if there is a blocking Transformer in between.


D'oh sorry for not reading carefully. But I played a little bit around with this scenario, and it seems that the key point is using a blocking transformer between the PythonCaller and the Terminator. You can put a large number of non-blocking transformer between the PythonCaller and the Terminator and you will get always the FATAL, but not if there is a blocking Transformer in between.

Yes, that is expected behaviour.

The presence of blocking transformer(s) before the Terminator allows the PythonCaller's PythonFactory to shut down cleanly before a feature reaches the Terminator.

The FeatureHolder is a blocking transformer that does not act on features so it would be an ideal transformer to use these cases.


Reply