How to run python scripts with default arguments in FastAPI?
Question:
I am new to FastAPI and I would like to ask for some explanation.
My code:
app_code.py:
import json
import argparse
def args():
parser = argparse.ArgumentParser("Some argumets")
parser.add_argument("--name", type=str)
parser.add_argument("--surname", type=str, nargs='?', default="Smith")
parser.add_argument("--birthday", type=str, nargs='?', default="2001")
args = parser.parse_args()
return args
def create_df(name):
ar = args()
print(ar)
x = {"name": name, "surname": ar.surname, "bd": ar.birthday}
x = json.dumps(x)
return x
if __name__ == "__main__":
args_all = args()
print(f"name: {args_all.name}, surname: {args_all.surname}, birthday:{args_all.birthday}")
print(create_df(args_all.name))
main_api.py
from fastapi import FastAPI
from app_code import *
app = FastAPI()
@app.get("/names")
async def root(name: str = 'none'):
print("In progress...")
result = create_df(name)
return result
When I run it normally, I mean run just script app by:
python app_code.py --name=James
I got proper result:
{name:James, surname:Smith, bd:2001}
But I have problems with arguments when I use it as a FastAPI web application. i.e., when I go to the browser and access:
api.addres.url/port/name?James
I got that error:
File "P:pythonProject3api.app_code.py", line 16, in create_df
ar = args()
File "P:pythonProject3api.app_code.py", line 11, in args
args = parser.parse_args()
File "C:UsersubuntAppDataLocalProgramsPythonPython39libargparse.py", line 1821, in parse_args
self.error(msg % ' '.join(argv))
File "C:UsersubuntAppDataLocalProgramsPythonPython39libargparse.py", line 2575, in error
self.exit(2, _('%(prog)s: error: %(message)sn') % args)
File "C:UsersubuntAppDataLocalProgramsPythonPython39libargparse.py", line 2562, in exit
_sys.exit(status)
SystemExit: 2
←[32mINFO←[0m: 127.0.0.1:50671 - "←[1mGET /names?name=James HTTP/1.1←[0m" ←[91m500 Internal Server Error←[0m
As you can see, I want to have some default arguments and some required to be passed by the user, such as name
, and I have a problem with those default parameters.
I mean, I know it’s because I use in my FastAPI only one method from script (can I just run whole script?), and that’s why I put ar=args()
there. But it did not fix my problem.
I just want to get JSON created by create_df()
method, when I just type in browser:
`api.addres.url/port/names?James` or `api.addres.url/port/name?James&?Potter`
Can someone explain me how to repair it?
Answers:
You could do that in your endpoint instead. By not declaring a default value for the query parameter, then it automatically means that this parameter is required.
As per the documentation (have a look here as well):
When you declare a default value for non-path parameters…then it is not required.
If you don’t want to add a specific value but just make it optional,
set the default as None.
But when you want to make a query parameter required, you can just not
declare any default value:
So, in your case, you could have something like this:
@app.get("/names")
def root(name: str, surname: str = "Smith", birthday: str = "2001"):
print("In progress...")
#result = create_df(name)
return {"name": name, "surname": surname, "bd": birthday}
In your browser, you can type, for instance: 127.0.0.1:8000/names?name=James
I am new to FastAPI and I would like to ask for some explanation.
My code:
app_code.py:
import json
import argparse
def args():
parser = argparse.ArgumentParser("Some argumets")
parser.add_argument("--name", type=str)
parser.add_argument("--surname", type=str, nargs='?', default="Smith")
parser.add_argument("--birthday", type=str, nargs='?', default="2001")
args = parser.parse_args()
return args
def create_df(name):
ar = args()
print(ar)
x = {"name": name, "surname": ar.surname, "bd": ar.birthday}
x = json.dumps(x)
return x
if __name__ == "__main__":
args_all = args()
print(f"name: {args_all.name}, surname: {args_all.surname}, birthday:{args_all.birthday}")
print(create_df(args_all.name))
main_api.py
from fastapi import FastAPI
from app_code import *
app = FastAPI()
@app.get("/names")
async def root(name: str = 'none'):
print("In progress...")
result = create_df(name)
return result
When I run it normally, I mean run just script app by:
python app_code.py --name=James
I got proper result:
{name:James, surname:Smith, bd:2001}
But I have problems with arguments when I use it as a FastAPI web application. i.e., when I go to the browser and access:
api.addres.url/port/name?James
I got that error:
File "P:pythonProject3api.app_code.py", line 16, in create_df
ar = args()
File "P:pythonProject3api.app_code.py", line 11, in args
args = parser.parse_args()
File "C:UsersubuntAppDataLocalProgramsPythonPython39libargparse.py", line 1821, in parse_args
self.error(msg % ' '.join(argv))
File "C:UsersubuntAppDataLocalProgramsPythonPython39libargparse.py", line 2575, in error
self.exit(2, _('%(prog)s: error: %(message)sn') % args)
File "C:UsersubuntAppDataLocalProgramsPythonPython39libargparse.py", line 2562, in exit
_sys.exit(status)
SystemExit: 2
←[32mINFO←[0m: 127.0.0.1:50671 - "←[1mGET /names?name=James HTTP/1.1←[0m" ←[91m500 Internal Server Error←[0m
As you can see, I want to have some default arguments and some required to be passed by the user, such as name
, and I have a problem with those default parameters.
I mean, I know it’s because I use in my FastAPI only one method from script (can I just run whole script?), and that’s why I put ar=args()
there. But it did not fix my problem.
I just want to get JSON created by create_df()
method, when I just type in browser:
`api.addres.url/port/names?James` or `api.addres.url/port/name?James&?Potter`
Can someone explain me how to repair it?
You could do that in your endpoint instead. By not declaring a default value for the query parameter, then it automatically means that this parameter is required.
As per the documentation (have a look here as well):
When you declare a default value for non-path parameters…then it is not required.
If you don’t want to add a specific value but just make it optional,
set the default as None.But when you want to make a query parameter required, you can just not
declare any default value:
So, in your case, you could have something like this:
@app.get("/names")
def root(name: str, surname: str = "Smith", birthday: str = "2001"):
print("In progress...")
#result = create_df(name)
return {"name": name, "surname": surname, "bd": birthday}
In your browser, you can type, for instance: 127.0.0.1:8000/names?name=James