1

I'm using fastAPI and uvicorn for my python app. I found out a tricky phenomenon using Uvicorn, which seems the way launching python code creating race condition.

My first trial is like below

# main.py
import uvicorn
app = App()

uvicorn.run(
    "main:app", 
    host="127.0.0.1", port=8080, log_level="debug", reload="true")

After launch main.py with python main.py, I experienced

ERROR: [Errno 48] Address already in use error.

I tried to find out any port or address bind with 127.0.0.1:8080 but there are no processes on my Mac.

However, my second trial like below:

import uvicorn
app = App()

if __name__ == "__main__":
    uvicorn.run(
        "main:app", 
        host="127.0.0.1", port=8080, log_level="debug", reload="true")

AFAIK, matching __name__ value means to check this module directly launched or just imported by other python module.

What does exactly happened behind this?

bad_coder
  • 11,289
  • 20
  • 44
  • 72
JSKIM
  • 195
  • 13
  • 2
    Does this answer your question? [What does if \_\_name\_\_ == "\_\_main\_\_": do?](https://stackoverflow.com/questions/419163/what-does-if-name-main-do) – polka Apr 18 '21 at 14:54
  • @polka The link you commented explained execution protection and I mentioned I already know about this usage. What I want to know is a phenomenon seems python interpreter tried to execute uvicorn server twice and I guess this makes `Address already in use` error. – JSKIM Apr 18 '21 at 15:10
  • 3
    I don't have knowledge about `uvicorn` specifically, but it looks like the `"main:app"` string you pass it means it is going to import your `main.py` script in order to access your `app` object. In that case you don't want `uvicorn.run` to trigger again when that function imports your script. It doesn't seem like a race condition to me. – kaya3 Apr 18 '21 at 15:13
  • I read links provided from this post, and found answer. First, there is no race condition what I misunderstood. Second, the address(process) collision found in uvicorn's reload process what I set to true(https://github.com/encode/uvicorn/blob/master/uvicorn/supervisors/basereload.py#L57). Uvicorn is watching `main:app` module for reloading and when without execution protection with `if`, python interpreter tried to execute uvicorn server(process) twice with same address. Thanks for advices:) @polka @kaya3 @electromeow – JSKIM Apr 18 '21 at 15:42
  • @JSKIM Nice! I'm not too familiar with this, but it seems like you solved the problem, right? Then you can [answer your own question](/help/self-answer) :) – wjandrea Apr 18 '21 at 15:55

1 Answers1

1

When you import a module by another file, the commands in it runs.
If you don't add that if statement, the uvicorn.run... command will run when you import it by another file.
So if you do that, only the functions, classes, etc. will be defined then you import it by another file. But not your uvicorn.run... command. Only when you run that file from command line, then uvicorn.run... command will run.
If you didn't understand, look here: https://www.freecodecamp.org/news/if-name-main-python-example/

electromeow
  • 211
  • 2
  • 8