顯示具有 python 標籤的文章。 顯示所有文章
顯示具有 python 標籤的文章。 顯示所有文章

2026年3月25日 星期三

利用telegram來控制 crontab 任務的啟動或關閉

既然用了telegram bot就想說用這個tool來控制系統中的crontab任務列表
先查看crontab -l
再利用crontab -e

再透過 python code:
import logging
from telegram import InlineKeyboardButton, InlineKeyboardMarkup, Update
from telegram.ext import Application, CommandHandler, CallbackQueryHandler, ContextTypes
from crontab import CronTab

# --- 設定區 ---
TOKEN = 'your bot token'
USER_ID = your chat id 不是字串

# 初始化日誌
logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO)

def get_cron_keyboard():
    cron = CronTab(user=True)
    keyboard = []
   
    for index, job in enumerate(cron):
        status_icon = "🟢 啟用中" if job.is_enabled() else "🔴 已暫停"
       
        # --- 自定義名稱邏輯 ---
        cmd = job.command
        if "email_notify_v2.py" in cmd:
            display_name = "任務通知 V2"
        elif "email_notify.py" in cmd:
            display_name = "任務通知 V1"
        else:
            # 如果不是以上兩個,就顯示指令的前 20 個字
            display_name = cmd.split('/')[-1][:20]
        # ---------------------

        label = f"{status_icon} | {display_name}"
        keyboard.append([InlineKeyboardButton(label, callback_data=str(index))])
   
    return InlineKeyboardMarkup(keyboard) if keyboard else None

async def start(update: Update, context: ContextTypes.DEFAULT_TYPE):
    """驗證身分並列出所有任務清單"""
    if update.effective_user.id != USER_ID:
        return
   
    markup = get_cron_keyboard()
    if markup:
        await update.message.reply_text("📋 **當前系統排程清單**\n點擊按鈕即可切換 啟動/暫停:",
                                      reply_markup=markup, parse_mode='Markdown')
    else:
        await update.message.reply_text("目前系統中沒有任何 Crontab 任務。")

async def button_callback(update: Update, context: ContextTypes.DEFAULT_TYPE):
    """處理按鈕點擊:切換任務狀態"""
    query = update.callback_query
    if query.from_user.id != USER_ID:
        await query.answer("權限不足")
        return

    await query.answer()
    job_index = int(query.data)
   
    # 重新讀取並操作
    cron = CronTab(user=True)
    try:
        job = cron[job_index]
        # 切換開關
        job.enable(not job.is_enabled())
        # 寫回系統
        cron.write()
       
        # 更新訊息與按鈕狀態
        await query.edit_message_text(
            text="✅ **狀態已更新**\n點擊下方按鈕繼續管理:",
            reply_markup=get_cron_keyboard(),
            parse_mode='Markdown'
        )
    except IndexError:
        await query.edit_message_text("❌ 找不到該任務,可能已被手動刪除。")

if __name__ == '__main__':
    app = Application.builder().token(TOKEN).build()
   
    app.add_handler(CommandHandler("start", start))
    app.add_handler(CallbackQueryHandler(button_callback))
   
    print("Bot 啟動中... 請在 Telegram 輸入 /start")
    app.run_polling()

運作情形

這樣控制定時任務就方便了!!!

2024年3月28日 星期四

python GUI

Purpose:
利用QT Designer設計一個python的介面, 來練習一些 影像處裡的python 程式.
Use QT Designer to design a python interface to practice some python programs in image processing.
1. 先用 Qt Designer 設計好界面,產生一個 .ui 檔
2. 進 Terminal 輸入以下指令產生可引入的 .py 檔
pyuic5 -x example.ui -o example_ui.py 主程式產生畫面用
pyuic5 -x tab.ui -o tab.py

Fundamental:
Anaconda3 install Qt Designer
pip install pyqt5
pip install pyqt5-tools
Anaconda3 install Opencv
pip install opencv-python

Python code:
Tab.py
# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'tab.ui'
#
# Created by: PyQt5 UI code generator 5.15.9
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again.  Do not edit this file unless you know what you are doing.


from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(894, 639)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.tabWidget = QtWidgets.QTabWidget(self.centralwidget)
        self.tabWidget.setGeometry(QtCore.QRect(0, 0, 600, 560))
        self.tabWidget.setObjectName("tabWidget")
        self.tab = QtWidgets.QWidget()
        self.tab.setObjectName("tab")
        self.label_2 = QtWidgets.QLabel(self.tab)
        self.label_2.setGeometry(QtCore.QRect(0, 0, 491, 531))
        self.label_2.setObjectName("label_2")
        self.pushButton = QtWidgets.QPushButton(self.tab)
        self.pushButton.setGeometry(QtCore.QRect(470, 0, 121, 31))
        self.pushButton.setObjectName("pushButton")
        self.pushButton_2 = QtWidgets.QPushButton(self.tab)
        self.pushButton_2.setGeometry(QtCore.QRect(470, 30, 121, 31))
        self.pushButton_2.setObjectName("pushButton_2")
        self.tabWidget.addTab(self.tab, "")
        self.tab_2 = QtWidgets.QWidget()
        self.tab_2.setObjectName("tab_2")
        self.label_3 = QtWidgets.QLabel(self.tab_2)
        self.label_3.setGeometry(QtCore.QRect(0, 0, 491, 531))
        self.label_3.setObjectName("label_3")
        self.pushButton_3 = QtWidgets.QPushButton(self.tab_2)
        self.pushButton_3.setGeometry(QtCore.QRect(470, 0, 121, 31))
        self.pushButton_3.setObjectName("pushButton_3")
        self.pushButton_4 = QtWidgets.QPushButton(self.tab_2)
        self.pushButton_4.setGeometry(QtCore.QRect(470, 30, 121, 31))
        self.pushButton_4.setObjectName("pushButton_4")
        self.tabWidget.addTab(self.tab_2, "")
        self.label = QtWidgets.QLabel(self.centralwidget)
        self.label.setGeometry(QtCore.QRect(610, 0, 191, 560))
        self.label.setObjectName("label")
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 894, 21))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        self.tabWidget.setCurrentIndex(1)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.label_2.setText(_translate("MainWindow", "TextLabel"))
        self.pushButton.setText(_translate("MainWindow", "PushButton"))
        self.pushButton_2.setText(_translate("MainWindow", "PushButton"))
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), _translate("MainWindow", "Tab 1"))
        self.label_3.setText(_translate("MainWindow", "TextLabel"))
        self.pushButton_3.setText(_translate("MainWindow", "PushButton"))
        self.pushButton_4.setText(_translate("MainWindow", "PushButton"))
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2), _translate("MainWindow", "Tab 2"))
        self.label.setText(_translate("MainWindow", "TextLabel"))

'''
if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    MainWindow = QtWidgets.QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)
    MainWindow.show()
    sys.exit(app.exec_())
'''

main.py
from WebCam import Ui_MainWindow
from PyQt5.QtWidgets import QApplication, QMainWindow

if __name__ == "__main__":
    import sys
    app = QApplication(sys.argv)
    MainWindow = QMainWindow()
    ui = Ui_MainWindow(MainWindow)
    MainWindow.show()
    sys.exit(app.exec_())

webcam.py
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtGui import QImage, QIcon, QPixmap, QPalette, QBrush, QColor, QFontDatabase, QFont
import sys
import cv2

class FrameGrabber(QtCore.QThread):
    def __init__(self, parent=None):
        super(FrameGrabber, self).__init__(parent)

    signal = QtCore.pyqtSignal(QtGui.QImage) # 建立信號物件

    def run(self):
        cap = cv2.VideoCapture(0)
        #cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 720)
        #cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1280)
        cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 640)
        cap.set(cv2.CAP_PROP_FRAME_WIDTH, 800)
        while cap.isOpened():
            success, frame = cap.read()
            if success:
                #image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) # 色彩轉換
                image = QtGui.QImage(frame, frame.shape[1], frame.shape[0], QtGui.QImage.Format_BGR888)
                self.signal.emit(image)  # 發送信號

class Ui_MainWindow(QtWidgets.QMainWindow):
    def __init__(self, MainWindow):
        super().__init__()
        self.MainWindow = MainWindow
        screen = QtWidgets.QApplication.desktop()
        width = screen.width()
        height = screen.height()
        print(width, height)
        line = str(width)+'\n'
        line += str(height)
       
        self.setupUi(self.MainWindow)
        self.label.setText(line)

        data = [
            ['test', 'gui', 20],
        ]
        #-----------------------------------------------------------------------
        #self.insert_data(self.tableWidget, data)
        '''
        self.grabber = FrameGrabber()
        self.grabber.signal.connect(self.updateFrame) # 監聽信號
        self.grabber.start()
        '''
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(894, 639)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.tabWidget = QtWidgets.QTabWidget(self.centralwidget)
        self.tabWidget.setGeometry(QtCore.QRect(0, 0, 600, 560))
        self.tabWidget.setObjectName("tabWidget")
        self.tab = QtWidgets.QWidget()
        self.tab.setObjectName("tab")
        self.label_2 = QtWidgets.QLabel(self.tab)
        self.label_2.setGeometry(QtCore.QRect(0, 0, 491, 531))
        self.label_2.setObjectName("label_2")
        self.pushButton = QtWidgets.QPushButton(self.tab)
        self.pushButton.setGeometry(QtCore.QRect(470, 0, 121, 31))
        self.pushButton.setObjectName("pushButton")
        self.pushButton.clicked.connect(self.videoRun)

        self.pushButton_2 = QtWidgets.QPushButton(self.tab)
        self.pushButton_2.setGeometry(QtCore.QRect(470, 30, 121, 31))
        self.pushButton_2.setObjectName("pushButton_2")
        self.pushButton_2.clicked.connect(self.quitApp)

        self.tabWidget.addTab(self.tab, "")
        self.tab_2 = QtWidgets.QWidget()
        self.tab_2.setObjectName("tab_2")
        self.label_3 = QtWidgets.QLabel(self.tab_2)
        self.label_3.setGeometry(QtCore.QRect(0, 0, 491, 531))
        self.label_3.setObjectName("label_3")
        self.pushButton_3 = QtWidgets.QPushButton(self.tab_2)
        self.pushButton_3.setGeometry(QtCore.QRect(470, 0, 121, 31))
        self.pushButton_3.setObjectName("pushButton_3")
        self.pushButton_4 = QtWidgets.QPushButton(self.tab_2)
        self.pushButton_4.setGeometry(QtCore.QRect(470, 30, 121, 31))
        self.pushButton_4.setObjectName("pushButton_4")
        self.tabWidget.addTab(self.tab_2, "")
        self.label = QtWidgets.QLabel(self.centralwidget)
        self.label.setGeometry(QtCore.QRect(610, 0, 191, 560))
        self.label.setObjectName("label")
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 894, 21))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        self.tabWidget.setCurrentIndex(0)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.label_2.setText(_translate("MainWindow", "TextLabel"))
        self.pushButton.setText(_translate("MainWindow", "OpenVedio"))
        self.pushButton_2.setText(_translate("MainWindow", "Quit"))
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), _translate("MainWindow", "Tab 1"))
        self.label_3.setText(_translate("MainWindow", "TextLabel"))
        self.pushButton_3.setText(_translate("MainWindow", "PushButton"))
        self.pushButton_4.setText(_translate("MainWindow", "PushButton"))
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2), _translate("MainWindow", "Tab 2"))
        self.label.setText(_translate("MainWindow", "TextLabel"))

    @QtCore.pyqtSlot(QtGui.QImage)
    def updateFrame(self, image):
        self.label_2.setPixmap(QtGui.QPixmap.fromImage(image))

    def insert_data(self, tableWidget, data):
        row0 = data[0] if len(data) else []
        tableWidget.setRowCount(len(data))
        tableWidget.setColumnCount(len(row0))
       
        for r, row in enumerate(data):
            for c, item in enumerate(row):
                tableWidget.setItem(r, c, QtWidgets.QTableWidgetItem(str(item)))    

    def quitApp(self):
        QtWidgets.QApplication.quit()
        '''
        line = "line 1"+'\n'
        line += "line 2"
        self.label.setText(line) #You can't call setText() twice
        '''
       
    def videoRun(self):
        self.grabber = FrameGrabber()
        self.grabber.signal.connect(self.updateFrame) # 監聽信號
        self.grabber.start()

YouTube Demo:


2024年1月31日 星期三

學習Python程式語言的工具


Anaconda是一個開源[5]的Python和R語言的發行版本,用於計算科學(資料科學、機器學習、大數據處理和預測分析),Anaconda致力於簡化軟體套件管理系統和部署。Anaconda透過Conda[6]進行軟體套件管理,並擁有許多適用於Windows、Linux和MacOS的資料科學軟體套件。


PyCharm是一個用於電腦編程的整合式開發環境(IDE),主要用於Python語言開發,由捷克公司JetBrains開發,提供代碼分析、圖形化除錯器,整合測試器、整合版本控制系統,並支援使用Django進行網頁開發。
PyCharm是一個跨平台開發環境,擁有Microsoft Windows、macOS和Linux版本。社群版在Apache授權條款下釋出,另外還有專業版在專用授權條款下釋出,其擁有許多額外功能,比如Web開發、Python We框架、Python剖析器、遠端開發、支援資料庫與SQL等更多進階功能。


Qt 是一個跨平台的 GUI 框架,支援 Windows、MacOS、Linux 等各大作業系統,其主要使用的程式語言是 C++,但想要在 Windows 上開發 C++ ⋯⋯摁想到要安裝 Compiler 我就頭痛,於是說到跨平台、最容易安裝、又最好入門的程式語言就是 Python 了,所以 Qt 同時推出了一個 Qt for Python,讓大家可以開心的用 Python 來編寫 GUI 應用程式。