Минимальный сценарий статического файлового сервера FastAPI

Я хочу написать минимальный статический файловый сервер 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/ находится в корневом каталоге? Или вместо этого вы пытаетесь смонтировать каталог my/, ссылаясь на каталог вместе со сценарием?

luk2302 23.11.2022 23:10

Корень. /my/directory — это путь в файловой системе. «ls /my/directory» возвращает файл .txt. У меня есть права на чтение/запись для этого каталога.

W.P. McNeill 23.11.2022 23:12

Когда uvicorn запускает свой воркер с модулем, который вы ему дали, он больше не будет работать __main__ (поскольку он импортирует модуль, который вы ему дали) - поэтому ваша установка не запускается, когда uvicorn фактически загружает модуль (и там нет sys.argv при запуске uvicorn, так как он загружает модуль, а не вызывается через шелл)

MatsLindh 23.11.2022 23:24
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
3
101
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Предположение, которое я сделал о том, что 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 24.11.2022 00:14

@ W.P.McNeill Здесь все работает отлично. python foo2.py "d:\foo\bar" с foo.txt в этом каталоге, а затем доступ к http://localhost:8000/static/foo.txt возвращает содержимое файла.

MatsLindh 24.11.2022 11:05

Неважно. Извини. Я делал ошибку на своей машине. Решение здесь верное. Пока строка server.mount не находится внутри раздела name == "main", все работает.

W.P. McNeill 24.11.2022 17:51

Когда вы вызываете 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 чище

M.O. 23.11.2022 23:43

Другие вопросы по теме