아마.. 이제 남은 기능이 2개다?
- ipynb 파일 업로드??
- 모델 테스트 이미지 업로드
ipynb 파일 업로드??
일단 프로젝트 폴더에 업로드 파일이 저장되게 해보자
main.py
@app.post("/models/{modelId}/ipynb")
async def update_file_ipynb(modelId: int, file: UploadFile, db: Session = Depends(get_db)):
file_path = Path.cwd()/file.filename
content = await file.read()
with open(file_path, 'wb') as fs:
fs.write(content)
return JSONResponse(content={"message": "업로드가 완료되었습니다."}, status_code=200)
주피터 노트북을 마크다운으로 변환하는 패키지를 설치한다.
https://github.com/jupyter/nbconvert
nbconvert 패키지 설치
pip install nbconvert
아까전에 프로젝트 폴더로 업로드된 test.ipynb을 nbconvert 패키지를 이용해서 마크다운으로 변환해보자
명령어
jupyter nbconvert --to <파일 포멧> <주피터노트북>
처럼 변환할 파일 포멧 과 주피터 노트북을 정해주면 변환해준다
마크다운으로 아까 업로드한 test.ipynb 를 변환할거니까.
jupyter nbconvert --to markdown .\test.ipynb
을 입력해주면
처럼 잘 변환해준다.. 이걸 코드로 작성해보자 파이썬 코드 안에서 명령어를 입력해주는 걸 검색해봤더니
3.x 부터 subprocess 라는게 추가되었다
https://docs.python.org/ko/3/library/subprocess.html
subprocess 모듈의 run() 함수를 사용해서 nbconvert 명령어를 실행 시켜보자
subprocess.run(["jupyter", "nbconvert", "--to", "markdown", file.filename])
를 추가 해서 테스트를 해보면
잘 만들어졌다.
근데 문제가 발생했다..
마크다운으로 변환시 이미지 파일이 따로 출력된다
알아 보던중
--ExtractOutputPreprocessor.enabled=False
를 추가하면 된다고 양키형들이 말해준다.
https://discourse.jupyter.org/t/convert-notebook-to-a-standalone-markdown/5363
subprocess.run(["jupyter", "nbconvert", "--to", "markdown", "--ExtractOutputPreprocessor.enabled=False", file.filename])
로 바꾸고 테스트 해보면!!
잘 바꿔준다!! 헤헤헿
이제 DB에 저장하는걸 해야겠다!!
with_suffix(".md") 으로 변환한 파일을 가져온다.
md_file_path = file_path.with_suffix(".md")
with open(md_file_path, 'r') as f:
md_content = f.read()
return JSONResponse(content={"message": "업로드가 완료되었습니다.", "md": md_content}, status_code=200)
로 변경해서 response 에 마크다운으로 변환된걸 잘 가져오는지 보자
잘 가져온다
이제 상단에 crud.py 사용할 model_ipynb 를 상단에 적어주고
# 상단에 model_ipynb 추가
from BE.crud import create_user, get_user, verify_password, get_user_info, update_user_info, get_models, get_my_models, create_model, get_model, user_image, email_code, check_email_code, user_image, user_model, model_ipynb
@app.post("/models/{modelId}/ipynb")
async def update_file_ipynb(modelId: int, file: UploadFile, db: Session = Depends(get_db)):
file_path = Path.cwd()/file.filename
content = await file.read()
with open(file_path, 'wb') as fs:
fs.write(content)
subprocess.run(["jupyter", "nbconvert", "--to", "markdown", "--ExtractOutputPreprocessor.enabled=False", file.filename])
md_file_path = file_path.with_suffix(".md")
with open(md_file_path, 'r') as f:
md_content = f.read()
model_ipynb(db, model_id = modelId, ipynb = md_content)
return JSONResponse(content={"message": "업로드가 완료되었습니다."}, status_code=200)
최종 코드로 이렇게 수정해준다..
그리고 crud.py
def model_ipynb(db: Session, model_id: int, ipynb: str):
db_model = db.query(Model).filter(Model.id == model_id).first()
db_model.description = ipynb
db.commit()
return db_model
으로 해서 변환한 마크다운 내용물을 description 컬럼에 넣는다.
테스트를 해보면!!
잘 들어가는걸 볼 수 있다!!
근데 여기서 아무것도 안해주면 업로드한 ipynb 와 md 파일들이 쌓이게 된다. 이걸 db에 저장이 되면 삭제해주자
os.remove() 로 삭제!!
os.remove(file_path)
os.remove(md_file_path)
테스트!!
끝!!
는.. 항상 끝났다고 생각했을때 문제가 있더라.. 파일이름이 한글일때 문제 발생
이것처럼 업로드 되는 파일이 한글이 들어갈 경우 오류가 발생함..
md_content = f.read() 에서 발행하는 오류이니 인코딩을 utf8 로 바꾸면 해결!!
성공!!!
모델 테스트 이미지 업로드
그냥 단순하게 body로 userId를 받아 오고 파일도 받아오려고 계속 시도하다가 공식문서를 읽게되었다.
fastapi 문서를 읽던 도중에
https://fastapi.tiangolo.com/tutorial/request-forms-and-files/#recap
마지막 부분에 이게 있었다??
대충 해석해 보면
다중 file 및 form 매개변수를 선언할수있는데 json 대신 form-data를 사용해서 json으로 전달 될 body 필드를 선언할 수 없다??
라는 뜻이고 마지막 줄에
이건 fastapi 가 아닌 http 프로토콜 부분이다! 라고 자기탓 아니라고 말해준다.. 흠..
에시 코드에 나와있는것처럼 userId를 form 으로 받으면 되겠다
여기서 코드를!!
@app.post("/models/{modelId}/img")
async def update_file_img(modelId: int, file: UploadFile, userId: int = Form(...), db: Session = Depends(get_db)):
return JSONResponse(content={"message": "업로드가 완료되었습니다. 분석 후 결과값이 출력됩니다."}, status_code=200)
파일 쪽은 그대로 쓰고 userId를 Form() 으로 받고
상단에 Form을 가져온다
# 상단에 File 추가
from fastapi import FastAPI, Depends, Form, HTTPException, File, UploadFile
print 를 찍어서 테스트를 해보면
잘 받아와 진다!!!
기존 업로드 코드에서 달라진 점은 저장되는 폴더와 db에 저장되는 테이블이 달라진다.
main.py에 나머지 코드를 작성해주고
# 상단에 model_img 를 추가
from BE.crud import create_user, get_user, verify_password, get_user_info, update_user_info, get_models, get_my_models, create_model, get_model, user_image, email_code, check_email_code, user_image, user_model, model_ipynb, model_img
@app.post("/models/{modelId}/img")
async def update_file_img(modelId: int, file: UploadFile, userId: int = Form(...), db: Session = Depends(get_db)):
file_path = await file.read()
s3_file_name = 'models_img/' + file.filename
s3_url = upload_to_s3(file_path, s3_file_name)
file.filename = s3_url
model_img(db, model_id = modelId, img= file.filename, user_id = userId)
return JSONResponse(content={"message": "업로드가 완료되었습니다. 분석 후 결과값이 출력됩니다."}, status_code=200)
crud.py 에 디비에 넣어줄 코드를 작성한다.
# 상단에 ModelImages 추가
from BE.models import User, Model, EmailAuth, ModelImages
def model_img(db: Session, model_id: int, img: str, user_id: int):
model_images = ModelImages(model_id= model_id, user_id= user_id, img_test= img)
db.add(model_images)
db.commit()
db.refresh(model_images)
return model_images
이렇게 작성해주고 테스트!!
잘된다!!
또 한주 시작되서.. k-mooc 강의 들어야되네.. 들으러 갑니다.
본 후기는 정보통신산업진흥원(NIPA)에서 주관하는 <AI 서비스완성! AI+웹개발 취업캠프 - 프론트엔드&백엔드> 과정 학습/프로젝트/과제 기록으로 작성되었습니다.
'코딩캠프 > AI 웹개발 취업캠프' 카테고리의 다른 글
[AI 웹개발 취업캠프] 77Day - 프로젝트 28일차 (0) | 2023.11.08 |
---|---|
[AI 웹개발 취업캠프] 76Day - 프로젝트 27일차 (0) | 2023.11.07 |
[AI 웹개발 취업캠프] 74Day - 프로젝트 25일차 (0) | 2023.11.04 |
[AI 웹개발 취업캠프] 73Day - 프로젝트 24일차 (0) | 2023.11.02 |
[AI 웹개발 취업캠프] 72Day - 프로젝트 23일차 (0) | 2023.11.01 |