Я хочу написать минимальный статический файловый сервер FastAPI, запускаемый из сценария, который позволяет указать каталог для совместного использования в командной строке. Следуя примеру из документации FastAPI, я написал это.
import uvicorn
from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles
server = FastAPI()
if __name__ == "__main__":
import sys
directory = sys.argv[1]
server.mount("/static", StaticFiles(directory=directory), name = "static")
uvicorn.run(app = "my_package:server")
Если я запущу это с аргументом /my/directory
, где этот каталог содержит file.txt
, я ожидаю, что смогу загрузить file.txt
по URL-адресу http://localhost:8000/static/file.txt
, но это возвращает HTTP 404.
Как мне написать этот минимальный сценарий статического файлового сервера?
Корень. /my/directory — это путь в файловой системе. «ls /my/directory» возвращает файл .txt. У меня есть права на чтение/запись для этого каталога.
Когда uvicorn запускает свой воркер с модулем, который вы ему дали, он больше не будет работать __main__
(поскольку он импортирует модуль, который вы ему дали) - поэтому ваша установка не запускается, когда uvicorn фактически загружает модуль (и там нет sys.argv
при запуске uvicorn, так как он загружает модуль, а не вызывается через шелл)
Предположение, которое я сделал о том, что sys.argv
недоступен, когда uvicorn загружает ваш модуль, неверно, поэтому он должен работать так, как вы ожидаете, переместив вашу статическую настройку за пределы __main__
guard:
import uvicorn
import sys
from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles
server = FastAPI()
directory = sys.argv[1]
server.mount("/static", StaticFiles(directory=directory), name = "static")
if __name__ == "__main__":
uvicorn.run(app = "my_package:server")
Это дает ту же ошибку HTTP 404, что и мой исходный скрипт. (Я также попробовал жестко кодировать каталог вместо чтения из sys.argv и получил тот же результат.)
@ W.P.McNeill Здесь все работает отлично. python foo2.py "d:\foo\bar"
с foo.txt
в этом каталоге, а затем доступ к http://localhost:8000/static/foo.txt
возвращает содержимое файла.
Неважно. Извини. Я делал ошибку на своей машине. Решение здесь верное. Пока строка server.mount не находится внутри раздела name == "main", все работает.
Когда вы вызываете uvicorn.run(app = "my_package:server")
, он фактически запускает отдельный процесс, в который импортируется my_package
. Поэтому все, что находится внутри if __name__ == "__main__":
, не будет запускаться в процессе uvicorn, поэтому ваша директория никогда не будет смонтирована.
Одним из возможных решений может быть получение каталога из переменной среды, которая устанавливается из небольшого скрипта bash:
from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles
server = FastAPI()
directory = os.getenv("DIRECTORY")
server.mount("/static", StaticFiles(directory=directory), name = "static")
start.sh
:
#!/usr/bin/env bash
DIRECTORY=$1 uvicorn mypackage:server
О, я не знал, что вы можете использовать sys.argv
будет доступно, в этом случае решение @MatsLindh чище
Действительно ли каталог /my/ находится в корневом каталоге? Или вместо этого вы пытаетесь смонтировать каталог my/, ссылаясь на каталог вместе со сценарием?