이번에 대학원생 안전교육 방식이 각 과목마다 동영상(15~25분) 하나 재생으로 바뀌었습니다.
저는 열심히 들었지만 혹시 학기 말에 너무 급해서 스킵하고 싶으신 분들이 계시다면 아래 코드를 입력해보세요.
크롬 : 과목 수강하기 클릭 -> 동영상 재생 -> F12 -> Console -> progressCheck(true) 입력 후 엔터
원리는 해당 동영상 재생 창의 Source 코드를 보면 대략 progressCheck가 false인지 true인지에 따라서 안전교육 수강 상태가 변경되는 것을 확인할 수 있습니다. 이를 보면 progressCheck에 true 값을 넣어주면 된다는 것을 볼 수 있고 실제로 입력하면 수강 완료됩니다.
from notion.client import NotionClient
from notion.block import *
from notion.collection import *
from datetime import datetime
import notion
def get_today_str():
today = datetime.today()
return f'{today.year}년 {today.month}월 {today.day}일'
token_v2 = '아까 복사한 token_v2 값' # token == 비밀번호 라고 생각하면 됩니다.
client = NotionClient(token_v2=token_v2) # Notion에 접속한다고 생각하면 됩니다.
url = '우리가 접근하려고 하는 notion page 주소' #우리가 수정하거나 정보를 받고 싶은 페이지의 url 주소를 입력해주세요.
page = client.get_block(url, force_refresh=True) # 해당 url의 메인 페이지를 불러올 수 있습니다.
## page.children을 print해보면 CollectionViewBlock 혹은 TableViewBlock이 존재한다고 나올겁니다.
myViewBlock = page.children[0] # 우리가 미리 만들어 놓은 테이블(ViewBlock)을 호출합니다.
new_row_of_my_table =myViewBlock.collection.add_row() # 우리가 만든 테이블의 데이터 모음을 collection이라고 부르는데 여기에 새로 가로 줄을 하나 추가해줍니다.
# 가로줄을 추가하는 순간 table view의 특성상 이름이 Untitled(안보임)인 페이지가 추가됩니다.
new_row_of_my_table.title = get_today_str()+' 체크리스트' # 새로운 가로줄의 이름을 설정하면 새로운 페이지가 눈에 보일 것입니다.
AM_check_list_toggle = myViewBlock.children.add_new(ToggleBlock, title='오전 체크리스트') # 누르면 펼쳐지고 또 다시 누르면 닫히는 Toggle 블럭을 우리가 새로 만든 페이지에 추가해줍니다.
## 위의 Toggle Block의 이름은 미리 title에서 지정해두었고 toggle의 하위 내용으로
## TodoBlock을 추가해줍니다.
AM_check_list_toggle.children.add_new(TodoBlock,title='8시 30분 전에 기상')
AM_check_list_toggle.children.add_new(TodoBlock,title='10시 30분 전에 출근')
AM_check_list_toggle.children.add_new(TodoBlock,title='새로운 메일 점검!')
# 이런식으로 추가해주세요.
# Notion은 블럭단위로 입력이 되는데 위와같이 코딩을 할 경우 한 줄씩 차례대로 입력되는 것을 볼 수 있습니다.
열심히 주석에 설명을 달아놓았으니 한번 사용해보고 입맛에 맞게 변경하여 사용하시면 됩니다.
체크리스트 자동화 시스템 - Linux, Ubuntu
열심히 만든 python 파일을 이제 자동으로 매일 실행시키는 코드만 남았습니다!
Linux의 crontab을 이용하면 손쉽게 자동으로 프로그램을 실행시킬 수 있습니다.
sudo nano /var/spool/cron/crontabs/{사용자이름}
위 명령어를 치면
이런 화면이 나옵니다.
맨 마지막에 명령어를 보면
5 2 * * * /opt~~/python /home~~~/upload_test.py
위 처럼 되어 있는데 5 2 * * * 는 매일 2시 5분에 자동으로 뒤에 나온 명령어를 실행시키라는 명령어입니다.
그렇다면 실제 명령어는
/opt~~/python /home~~~/upload_test.py
이 명령어가 실행이 되는데 가상 환경을 쓰셨다면 가상 환경의 bin 폴더 내 python 위치 띄우고 아까 작성한 python 파일 위치를 지정하시면 매일 새벽 2시 5분에 체크리스트가 새로 추가되는 것을 확인하실 수 있습니다!
중간에 gdrive 명령어는 제가 엑셀에 적은 일정 내용을 자동으로 구글 캘린더랑 연동시키는 프로그램을 자동화한 건데 귀찮아서 안 쓰고 있습니다...
결론
컴퓨터를 실험 때문에 항상 켜 두는 입장이라 저는 이런 자동화 환경이 가능하지만 아닌 분들은 그냥 notion에 템플릿을 등록해두고 매일 추가해주시면 편할 거예요. 굳이 이렇게 귀찮다고 코딩하는 분들은 많이 없길 바랍니다!
import torch
import numpy as np
# Torch 버전 확인
print(torch.__version__)
# CUDA 동작 확인?
print(torch.cuda.is_available())
print("=================== 구분선 ====================")
# Torch 원하는 Shape 만들기 /rand 사용
# rand는 0부터 1사이의 랜덤한 소수점 4자리 만드는 듯
print(torch.rand(1,2)) # (3,6) 이면 size가 (3 x 6) 으로 표시 (행, 열)
print(torch.rand(1,2,3)) # 괄호가 있든 없든 아래와 같은 결과
print(torch.rand([1,2,3])) #[]든 ()든 상관 없다.
print(torch.rand((1,2,3))) # (1,2,3) 이면 size가 (1 x 2 x 3) 으로 표시
print(torch.rand((2,2,3))) # (n, 행, 열) (행, 열이 이미지라면 n은 이미지 개수)
# 더 늘어난다면?? (3,4,5,6)이라고 생각해보면 5x6 이미지가 4개가 묶여있는 것이 3개가 묶여있다!
print("=================== 구분선 ====================")
# 위의 값들은 Variable?일까?
print(torch.is_tensor(torch.rand(1,1)))
print("=================== 구분선 ====================")
# 일단 Tensor인걸로 결과도 FloatTensor로 나온다.
# 그럼 위의 값들은 cuda 사용되는 Tensor?
# CUDA는 아래방법을 쓰면 될듯
# dtype 을 정의해놓고 쓰자
dtype1 = torch.FloatTensor
dtype2 = torch.cuda.FloatTensor
a = torch.rand(1,2,3)
# a.fill_(3.5) # 원하는 값으로 채워버리기
# a = a.add(4.0) #원하는 값 더해버리기
b = torch.rand(1,2,3)
c = torch.rand(2,2,3)
d = torch.rand(2,1,2,3)
# Variable 만들면서 텐서를 하나만 넣을 수 있다고함,
# Variable 은 autograd 안에 있음
# requires_grad는 뭔지 모르겠다.
print(torch.autograd.Variable(a.type(dtype1),requires_grad=False))
print(torch.autograd.Variable(a.type(dtype2))) # 이러면 Cuda 사용하는 텐서
# 근데 GPU 0이 지정된거 보면
# GPU도 원하는 거 지정가능하지 않을까
# print(torch.autograd.Variable(a,a,a,a)) 이러면 error
print("=================== 구분선 ====================")
# TODO: Variable에서 Tensor로 변환
Test_Variable_to_Tensor =torch.autograd.Variable(a.type(dtype1))
print(Test_Variable_to_Tensor.data)
# TODO: Tensor에서 numpy로 변환
a_np = a.numpy()
print(a_np)
# TODO: Variable에서 numpy로 변환
print(Test_Variable_to_Tensor.data.numpy())
# TODO: numpy to Tensor to Variable
np_rand = np.random.rand(1,2,3)
print(np_rand)
np_to_tensor = torch.from_numpy(np_rand)
print(np_to_tensor)
np_to_Variable = torch.autograd.Variable(np_to_tensor.type(dtype1))
print(np_to_Variable)
print("=================== 구분선 ====================")
# 사칙연산
# Tensor 영역
# Variable 영역
t1 = torch.rand(1,2,3)
t2 = torch.rand(3,2,1)
t3 = torch.FloatTensor([[[1,2,3],[-1,-2,-3]]]) # size 1,2,3
t4 = torch.FloatTensor([[[1],[2]],[[3],[4]],[[5],[6]]]) # size 3,2,1
t5 = torch.rand(1,3,2)
t6 = torch.rand(2,3,2)
t7 = torch.rand(2,2,3)
print(t3, "t3", t4, "t4")
V1 = torch.autograd.Variable(t3.type(dtype1))
V2 = torch.autograd.Variable(t1.type(dtype1))
V3 = torch.autograd.Variable(t1.type(dtype2))
V4 = torch.autograd.Variable(t4.type(dtype1))
V5 = torch.autograd.Variable(t5.type(dtype1))
V6 = torch.autograd.Variable(t6.type(dtype1))
V7 = torch.autograd.Variable(t7.type(dtype1))
# Variable 덧셈
print(V1+V2) # 단순 덧셈 가능
print(torch.add(V1,2)) # 원하는 값 덧셈 가능
# Variable 덧셈 그냥 + Cuda
# print(V1+V3) # CUDA와 그냥은 더할 수 없다!
# print(torch.add(V1+V3)) #이것도 마찬가지!
# GPU 영역의 Tensor, Variable들과 CPU 영역의 Tensor, Variable들과 연산 불가
# 따로 도는 건 가능한 듯 하다.
# Variable 곱셈
print(V1,V4, V1*V4) # error 발생 안함 why?
print(torch.mul(V1,V4))
# 두 결과 모두 같은 결과를 보임
# 두 결과는 [1 2 3] [1 1 1] 확장을 해서 각 인스턴스별로 곱한 결과를 보임
# [-1 -2 -3] [2 2 2]
# print(torch.matmul(V1,V4)) # error 발생 함 사이즈 오류 1x2x3와 3x2x1 인데 2x3과 2x1이 들어가는듯 맨 앞은 배치
# 위로 알아낸 사실은 matmul은 아마 2d matrix multiply이기 때문에 저런식으로 오류가 나는게 아닐까 싶다.
# 그러면 다음 size가 같은거 하면?
# print(torch.matmul(V1,V2)) # 마찬가지로 error 자동변환 ㄴㄴ
# Next 그러면 1x2x3과 1x3x2는 잘 동작하겠지?
print(torch.matmul(V1,V5)) # 결과물 1x2x2 잘 동작 한다.
# 그러면 1x2x3과 2x3x2는? 2x2x3과 2x3x2는?
print(torch.matmul(V1,V6)) # 결과물 2x2x2 잘 동작 한다. 이 경우 1x2x3을 각 1x3x2에 matmul하는 것이고
print(torch.matmul(V7,V6)) # 결과물 2x2x2 잘 동작 한다. 이 경우 각 1x2x3을 각 1x3x2에 matmul 하는 것?
# TODO: 1x2x3 이런식으로 3차원인경우 맨 앞 차원은 배치로 들어간다. 그렇다면 4차원인경우도 가능한가?
print("=================== 구분선 ====================")
#
# TODO : 원하는 Shape의 Vairable 만들기