0

Keras forces output to sys.stderr (for which a fix was rejected on GitHub). There seems to be a problem writing to system outputs from a child process in a Web App. This leads to my code throwing the appropriate error when attempting to inform about the backend implementation when Keras is imported.

AttributeError: 'NoneType' object has no attribute 'write'

I tried to redirect output to os.devnull according to this answer before instantiating a Flask application and starting it with a web.config. However, the error persisted. Curiously, writing output without multiprocessing worked just fine.

import sys
from flask import Flask
import keras

app = Flask(__name__)


@app.route('/')
def main():
    print('Hello!')
    sys.stdout.write('test\n')
    sys.stderr.write('emsg\n')
    return 'OK.', 200

Even from keras import backend as k works. That's the statement that originally produced the error. This left me baffled. What could possibly be the matter?

Minimal example

In my application, a sub process is spawned for training models. When trying to write output within the multiprocessing.Process, an error is thrown. Here's some code to reproduce the situation.

import sys
from flask import Flask
from multiprocessing import Process


def write_output():
    sys.stdout.write('hello\n')


def create_app():
    apl = Flask(__name__)
    Process(target=write_output).start()

    @apl.route('/')
    def main():
        return 'OK.', 200

    return apl

This application is then instantiated in another file and called from web.config. Basic logging confirmed the error was still being thrown.


Almost a fix

Although not a fix, I got the system working using threading. By simply switching multiprocessing.Queue and Process to queue.Queue and threading.Thread, no errors like above are thrown. For my use case this is acceptable for now. Of course it's not a solution to the problem of writing output in a child process.

Felix
  • 2,548
  • 19
  • 48

1 Answers1

0

I noticed that you mentioned the web.config file for Azure WebApp on Windows. And there is a limitation about Azure Web App sandbox you need to know. After I reviewed it with your scenario, I think your app was rejected by some restrictions. Per my experience, I think the task of trainning model is not suitable for running on Azure WebApp, especially for a Windows instance, even just on a sandbox based on CPU.

My suggestion is to move your app to a high-performace Azure VM with GPU, such as NC-series you can see from https://azure.microsoft.com/en-us/pricing/details/virtual-machines/linux/.

enter image description here

Otherwise, you may have other reason to use Azure WebApp for your app, I recommanded that you could try Azure WebApp for Linux based on Docker.

Hope it helps.

Peter Pan
  • 23,476
  • 4
  • 25
  • 43
  • Thank you very much for the suggestions and the documentation link! We have considered the Linux-based version, but Hybrid Connections are [not available](https://feedback.azure.com/forums/169385-web-apps/suggestions/18948526-hybrid-connection-manager-support-for-linux) there. Additionally, the models are rather small, so a CPU will do fine. Do you have and idea as to what would be the basis of rejecting this simple app? I could not find anything but "access to console". Still, writing output in the main process seems to be fine. I'm a bit confused. – Felix May 27 '19 at 07:07
  • @Felix I think the basis of rejecting is the depth of the tree of processes in the sandbox. The `w3wp` of IIS starts up flask, the flask invokes keras, and the keras need to call tensorflow C++ runtime which may parallelly run via multiprocesses or multi-threads via windows kernel. A words said in [`Definition of the sandbox`](https://github.com/projectkudu/kudu/wiki/Azure-Web-App-sandbox#definition-of-the-sandbox), "These processes are grouped together and are collectively subject to a single set of limits, all enforced within the underlying Windows kernel." – Peter Pan May 27 '19 at 07:52
  • I see. But at least there is no mention of the process tree depth limitation (that caught my eye anyway). And my example above produces the error with only spawning one process below Python, and the error seems unrelated. Have you encountered this kind of process depth problem before? – Felix May 27 '19 at 07:55
  • @Felix I suggested you could consider to use a small Linux VM like B-series, which has more performance and a suitable pricing with WebApp. Then, a P2S VPN Gateway can be used for [Linux](https://learn.microsoft.com/en-us/azure/vpn-gateway/vpn-gateway-certificates-point-to-site-linux). – Peter Pan May 27 '19 at 07:57
  • @Felix No, just my guess. I will never train a model on WebApp, it doesn't suit. – Peter Pan May 27 '19 at 08:01