2019年12月10日 星期二

#桌面上的計算機(二)--建立計算機

--使用PyQt套件

#原文出處

#摘要紀錄與說明
--python的GUI套件,有 Tkinter, wxPython, PyQt, PySide2...等等
--PyQt5 是基於Qt5而來

--請直接下載檔案執行如果是複製網頁上的程式,貼上後請注意縮排問題。

#一步一步建立「py小計算機」
        1. #01-建立外殼  pycalc01.py
        2. import sys

        3. from PyQt5.QtWidgets import QApplication  #qt應用程式
        4. from PyQt5.QtWidgets import QMainWindow  #qt主視窗
        5. from PyQt5.QtWidgets import QWidget  #qt總部件
        6. #from PyQt5 import QtGui  #為了加一個window icon,這裡可以省略。

        7. #這是原作者,感謝。
        8. __version__ '0.1'
        9. __author__ 'Leodanis Pozo Ramos'

        10. #定義主視窗,繼承自QMainWindow
        11. class PyCalcUi(QMainWindow):
        12.     #初始化,訂定視窗外觀
        13.     def __init__(self):
        14.         super().__init__()
        15.         self.setWindowTitle('py小計算機')
        16.         self.setFixedSize(235235#固定大小,免得計算機變形。
        17.         # 建立中央部件
        18.         self._centralWidget QWidget(self)  #先建立總部件實體(self相當於parent=self,top level的物件沒有parent了,所以不能省略。)
        19.         self.setCentralWidget(self._centralWidget)  #再設定成中央部件
        20.         #self.setWindowIcon(QtGui.QIcon('icon.png'))  #這行將icon放上去。這行可以省略。

        21. # 主程式
        22. def main():
        23.     pycalc QApplication(sys.argv)  #建立app
        24.     view PyCalcUi()  #建立主視窗實體
        25.     
        26.     view.show()  
        27.     sys.exit(pycalc.exec())

        28. if __name__ == '__main__':
        29.     main()
          1. #02-建立外觀  pycalc02.py
          2. import sys

          3. from PyQt5.QtWidgets import QApplication  #qt應用程式
          4. from PyQt5.QtWidgets import QMainWindow  #qt主視窗
          5. from PyQt5.QtWidgets import QWidget  #qt總部件
          6. from PyQt5 import QtGui  #為了加一個window icon,這裡可以省略。
          7. from PyQt5.QtCore import Qt  #一般性質的設定
          8. from PyQt5.QtWidgets import QGridLayout  #格狀排列
          9. from PyQt5.QtWidgets import QLineEdit   #單行文字
          10. from PyQt5.QtWidgets import QPushButton  #按鈕
          11. from PyQt5.QtWidgets import QVBoxLayout  #垂直排列

          12. #這是原作者,感謝。
          13. __version__ '0.1'
          14. __author__ 'Leodanis Pozo Ramos'

          15. #定義主視窗,繼承自QMainWindow
          16. class PyCalcUi(QMainWindow):
          17.     #初始化,訂定視窗外觀
          18.     def __init__(self):
          19.         super().__init__()
          20.         self.setWindowTitle('py小計算機')
          21.         self.setFixedSize(235235#固定大小,免得計算機變形。
          22.         self.generalLayout QVBoxLayout() #整體的部件是垂直排列
          23.         # 建立中央部件
          24.         self._centralWidget QWidget(self)  #先建立總部件實體(self相當於parent=self,top level的物件沒有parent了,所以不能省略。)
          25.         self.setCentralWidget(self._centralWidget)  #再設定成中央部件
          26.         self._centralWidget.setLayout(self.generalLayout)  #中央部件就設定為整體垂直排列
          27.         self._createDisplay() #計算機顯示數字的部件
          28.         self._createButtons() #計算機顯示按鈕的部件

          29.         #self.setWindowIcon(QtGui.QIcon('icon.png'))  #這行將icon放上去。這行可以省略。
          30.     
          31.     #計算機顯示數字的部件
          32.     def _createDisplay(self):
          33.         self.display QLineEdit() #顯示只要一行
          34.         self.display.setFixedHeight(35)  #顯示幕的高度
          35.         self.display.setAlignment(Qt.AlignRight)  #靠右顯示
          36.         self.display.setReadOnly(True)  #設定唯讀
          37.         
          38.         self.generalLayout.addWidget(self.display#將以上設定加入整體垂直設定中
          39.         
          40.     def _createButtons(self):
          41.         self.buttons = {}
          42.         buttonsLayout QGridLayout()
          43.         #在字典中,設定按鈕顯示的數字和在格狀排列中的座標
          44.         buttons = {'7': (00),
          45.                    '8': (01),
          46.                    '9': (02),
          47.                    '/': (03),
          48.                    'C': (04),
          49.                    '4': (10),
          50.                    '5': (11),
          51.                    '6': (12),
          52.                    '*': (13),
          53.                    '(': (14),
          54.                    '1': (20),
          55.                    '2': (21),
          56.                    '3': (22),
          57.                    '-': (23),
          58.                    ')': (24),
          59.                    '0': (30),
          60.                    '00': (31),
          61.                    '.': (32),
          62.                    '+': (33),
          63.                    '=': (34),
          64.                   }
          65.         #取出字典中的文字和座標,一一擺進格狀排列中
          66.         for btnTextpos in buttons.items():
          67.             self.buttons[btnText] = QPushButton(btnText)  #設定按鈕實體,以及顯示的文字
          68.             self.buttons[btnText].setFixedSize(4040)    #設定按鈕大小
          69.             buttonsLayout.addWidget(self.buttons[btnText], pos[0], pos[1])  #擺進格狀排列
          70.             
          71.           self.generalLayout.addLayout(buttonsLayout)#將以上設定加入整體垂直設定中
          72. # 主程式
          73. def main():
          74.     pycalc QApplication(sys.argv)  #建立app
          75.     view PyCalcUi()  #建立主視窗實體
          76.     
          77.     view.show()  
          78.     sys.exit(pycalc.exec())

          79. if __name__ == '__main__':
          80.     main()
  • 處理view的部份--也就是計算機面板上的訊號-- pycalc03.py
  1. 面板顯示
  2. 計算式
  3. 按鍵狀態
          1. #03-建立Controller,處理view訊號,只剩=還沒處理。  pycalc03.py
          2. import sys

          3. from PyQt5.QtWidgets import QApplication  #qt應用程式
          4. from PyQt5.QtWidgets import QMainWindow  #qt主視窗
          5. from PyQt5.QtWidgets import QWidget  #qt總部件
          6. from PyQt5 import QtGui  #為了加一個window icon,這裡可以省略。
          7. from PyQt5.QtCore import Qt  #一般性質的設定
          8. from PyQt5.QtWidgets import QGridLayout  #格狀排列
          9. from PyQt5.QtWidgets import QLineEdit   #單行文字
          10. from PyQt5.QtWidgets import QPushButton  #按鈕
          11. from PyQt5.QtWidgets import QVBoxLayout  #垂直排列
          12. from functools import partial  #有關function的工作

          13. #這是原作者,感謝。
          14. __version__ '0.1'
          15. __author__ 'Leodanis Pozo Ramos'

          16. #定義主視窗,繼承自QMainWindow
          17. class PyCalcUi(QMainWindow):
          18.     #初始化,訂定視窗外觀
          19.     def __init__(self):
          20.         super().__init__()
          21.         self.setWindowTitle('py小計算機')
          22.         self.setFixedSize(235235#固定大小,免得計算機變形。
          23.         self.generalLayout QVBoxLayout() #整體的部件是垂直排列
          24.         # 建立中央部件
          25.         self._centralWidget QWidget(self)  #先建立總部件實體(self相當於parent=self,top level的物件沒有parent了,所以不能省略。)
          26.         self.setCentralWidget(self._centralWidget)  #再設定成中央部件
          27.         self._centralWidget.setLayout(self.generalLayout)  #中央部件就設定為整體垂直排列
          28.         self._createDisplay() #計算機顯示數字的部件
          29.         self._createButtons() #計算機顯示按鈕的部件

          30.         #self.setWindowIcon(QtGui.QIcon('icon.png'))  #這行將icon放上去。這行可以省略。
          31.     
          32.     #計算機顯示數字的部件
          33.     def _createDisplay(self):
          34.         self.display QLineEdit() #設定display,顯示只要一行
          35.         self.display.setFixedHeight(35)  #顯示幕的高度
          36.         self.display.setAlignment(Qt.AlignRight)  #靠右顯示
          37.         self.display.setReadOnly(True)  #設定唯讀
          38.         
          39.         self.generalLayout.addWidget(self.display#將以上設定加入整體垂直設定中
          40.         
          41.     def _createButtons(self):
          42.         self.buttons = {}
          43.         buttonsLayout QGridLayout()
          44.         #在字典中,設定按鈕顯示的數字和在格狀排列中的座標
          45.         buttons = {'7': (00),
          46.                    '8': (01),
          47.                    '9': (02),
          48.                    '/': (03),
          49.                    'C': (04),
          50.                    '4': (10),
          51.                    '5': (11),
          52.                    '6': (12),
          53.                    '*': (13),
          54.                    '(': (14),
          55.                    '1': (20),
          56.                    '2': (21),
          57.                    '3': (22),
          58.                    '-': (23),
          59.                    ')': (24),
          60.                    '0': (30),
          61.                    '00': (31),
          62.                    '.': (32),
          63.                    '+': (33),
          64.                    '=': (34),
          65.                   }
          66.         #取出字典中的文字和座標,一一擺進格狀排列中
          67.         for btnTextpos in buttons.items():
          68.             self.buttons[btnText] = QPushButton(btnText)  #設定按鈕實體,以及顯示的文字
          69.             self.buttons[btnText].setFixedSize(4040)    #設定按鈕大小
          70.             buttonsLayout.addWidget(self.buttons[btnText], pos[0], pos[1])  #擺進格狀排列
          71.             
          72.             self.generalLayout.addLayout(buttonsLayout)#將以上設定加入整體垂直設定中
          73.     #補PyCalcUi的3個methods,在PyCalcCtrl中被呼叫。
          74.     def setDisplayText(selftext):
          75.         """Set display's text."""
          76.         self.display.setText(text)
          77.         self.display.setFocus()

          78.     def displayText(self):
          79.         """Get display's text."""
          80.         return self.display.text()

          81.     def clearDisplay(self):
          82.         """Clear the display."""
          83.         self.setDisplayText("")
          84.             
          85. #建立Controller
          86. class PyCalcCtrl:
          87.     def __init__(selfview):
          88.         self._view view  #初始化參數view(PyCalcUi實體)
          89.         self._connectSignals() #呼叫方法
          90.     
          91.     #顯示幕上的文字處理
          92.     def _buildExpression(selfsub_exp):
          93.         expression self._view.displayText() + sub_exp
          94.         self._view.setDisplayText(expression)
          95.     
          96.     #連結事件和處理程式
          97.     def _connectSignals(self):
          98.         #掃描所有按鍵,有click,就呼叫_buildExpression。
          99.         for btnTextbtn in self._view.buttons.items():
          100.             if btnText not in {'=''C'}:
          101.                 btn.clicked.connect(partial(self._buildExpressionbtnText)) #有click,才會呼叫_buildExpression

          102.         self._view.buttons['C'].clicked.connect(self._view.clearDisplay)
          103.     
          104. # 主程式
          105. def main():
          106.     pycalc QApplication(sys.argv)  #建立app
          107.     view PyCalcUi()  #建立主視窗實體
          108.     view.show()  #顯示
          109.     
          110.     #處理按鍵和顯示幕的文字
          111.     PyCalcCtrl(view=view)

          112.     sys.exit(pycalc.exec())

          113. if __name__ == '__main__':
          114.     main()
  • 最後的計算及按錯時的處理。  pycalc04.py
  1. #04-完整程式。
  2. #處理「=」「enter」事件及計算答案。  pycalc04.py

  3. import sys

  4. from PyQt5.QtWidgets import QApplication  #qt應用程式
  5. from PyQt5.QtWidgets import QMainWindow  #qt主視窗
  6. from PyQt5.QtWidgets import QWidget  #qt總部件
  7. from PyQt5 import QtGui  #為了加一個window icon,這裡可以省略。
  8. from PyQt5.QtCore import Qt  #一般性質的設定
  9. from PyQt5.QtWidgets import QGridLayout  #格狀排列
  10. from PyQt5.QtWidgets import QLineEdit   #單行文字
  11. from PyQt5.QtWidgets import QPushButton  #按鈕
  12. from PyQt5.QtWidgets import QVBoxLayout  #垂直排列
  13. from functools import partial  #有關function的工作

  14. #這是原作者,感謝。
  15. __version__ '0.1'
  16. __author__ 'Leodanis Pozo Ramos'

  17. ERROR_MSG '算式錯誤'
  18. #定義主視窗,繼承自QMainWindow
  19. class PyCalcUi(QMainWindow):
  20.     #初始化,訂定視窗外觀
  21.     def __init__(self):
  22.         super().__init__()
  23.         self.setWindowTitle('py小計算機')
  24.         self.setFixedSize(235235#固定大小,免得計算機變形。
  25.         self.generalLayout QVBoxLayout() #整體的部件是垂直排列
  26.         # 建立中央部件
  27.         self._centralWidget QWidget(self)  #先建立總部件實體(self相當於parent=self,top level的物件沒有parent了,所以不能省略。)
  28.         self.setCentralWidget(self._centralWidget)  #再設定成中央部件
  29.         self._centralWidget.setLayout(self.generalLayout)  #中央部件就設定為整體垂直排列
  30.         self._createDisplay() #計算機顯示數字的部件
  31.         self._createButtons() #計算機顯示按鈕的部件

  32.         #self.setWindowIcon(QtGui.QIcon('icon.png'))  #這行將icon放上去。這行可以省略。
  33.     
  34.     #計算機顯示數字的部件
  35.     def _createDisplay(self):
  36.         self.display QLineEdit() #設定display,顯示只要一行
  37.         self.display.setFixedHeight(35)  #顯示幕的高度
  38.         self.display.setAlignment(Qt.AlignRight)  #靠右顯示
  39.         self.display.setReadOnly(True)  #設定唯讀
  40.         
  41.         self.generalLayout.addWidget(self.display#將以上設定加入整體垂直設定中
  42.         
  43.     def _createButtons(self):
  44.         self.buttons = {}
  45.         buttonsLayout QGridLayout()
  46.         #在字典中,設定按鈕顯示的數字和在格狀排列中的座標
  47.         buttons = {'7': (00),
  48.                    '8': (01),
  49.                    '9': (02),
  50.                    '/': (03),
  51.                    'C': (04),
  52.                    '4': (10),
  53.                    '5': (11),
  54.                    '6': (12),
  55.                    '*': (13),
  56.                    '(': (14),
  57.                    '1': (20),
  58.                    '2': (21),
  59.                    '3': (22),
  60.                    '-': (23),
  61.                    ')': (24),
  62.                    '0': (30),
  63.                    '00': (31),
  64.                    '.': (32),
  65.                    '+': (33),
  66.                    '=': (34),
  67.                   }
  68.         #取出字典中的文字和座標,一一擺進格狀排列中
  69.         for btnTextpos in buttons.items():
  70.             self.buttons[btnText] = QPushButton(btnText)  #設定按鈕實體,以及顯示的文字
  71.             self.buttons[btnText].setFixedSize(4040)    #設定按鈕大小
  72.             buttonsLayout.addWidget(self.buttons[btnText], pos[0], pos[1])  #擺進格狀排列
  73.             
  74.         self.generalLayout.addLayout(buttonsLayout)#將以上設定加入整體垂直設定中
  75.     
  76.     def setDisplayText(selftext):
  77.         """Set display's text."""
  78.         self.display.setText(text)
  79.         self.display.setFocus()

  80.     def displayText(self):
  81.         """Get display's text."""
  82.         return self.display.text()

  83.     def clearDisplay(self):
  84.         """Clear the display."""
  85.         self.setDisplayText("")

  86. #這是一個獨立的functions,就是model部份        
  87. def evaluateExpression(expression):
  88.     try:
  89.         result str(eval(expression, {}, {})) #eval(expressionglobals=Nonelocals=None)全域變數和區域變數
  90.     except Exception:
  91.         result ERROR_MSG

  92.     return result
  93.     
  94. #建立Controller
  95. class PyCalcCtrl:
  96.     #Control溝通model和view:view處理所有的顯示,model處理所有的後端計算,Control就是二者的交會處。
  97.     def __init__(self,modelview):
  98.         self._evaluate model #model就是evaluateExpression
  99.         self._view view  #初始化參數view(PyCalcUi實體)
  100.         self._connectSignals() #呼叫方法
  101.     
  102.     #計算答案,間接承接自model的function,來算答案。
  103.     def _calculateResult(self):
  104.         result self._evaluate(expression=self._view.displayText())
  105.         self._view.setDisplayText(result)

  106.     #顯示幕上的文字處理
  107.     def _buildExpression(selfsub_exp):
  108.         #先檢查,如果之前是錯誤的訊息,就先清除
  109.         if self._view.displayText() == ERROR_MSG:
  110.             self._view.clearDisplay()

  111.         expression self._view.displayText() + sub_exp
  112.         self._view.setDisplayText(expression)
  113.     
  114.     #連結事件和處理程式
  115.     def _connectSignals(self):
  116.         #掃描所有按鍵,有click,就呼叫_buildExpression。
  117.         for btnTextbtn in self._view.buttons.items():
  118.             if btnText not in {'=''C'}:
  119.                 btn.clicked.connect(partial(self._buildExpressionbtnText)) #有click,才會呼叫_buildExpression
  120.                 
  121.         self._view.buttons['='].clicked.connect(self._calculateResult#按=就算答案
  122.         self._view.display.returnPressed.connect(self._calculateResult#按enter就算答案

  123.         self._view.buttons['C'].clicked.connect(self._view.clearDisplay)
  124.     
  125. # 主程式
  126. def main():
  127.     pycalc QApplication(sys.argv)  #建立app
  128.     view PyCalcUi()  #建立主視窗實體
  129.     view.show()  #顯示
  130.     
  131.     #處理按鍵和顯示幕的文字,model算出答案
  132.     model evaluateExpression
  133.     PyCalcCtrl(model=modelview=view)

  134.     sys.exit(pycalc.exec())

  135. if __name__ == '__main__':
  136.     main()

#桌面上的計算機(一)--基礎認識

--使用PyQt套件

#原文出處

#摘要紀錄與說明
--python的GUI套件,有 Tkinter, wxPython, PyQt, PySide2...等等
--PyQt5 是基於Qt5而來

--請直接下載檔案執行如果是複製網頁上的程式,貼上後請注意縮排問題。
--程式碼的說明,就在程式裡。

#測試小部件
  • 建立虛擬環境    python -m venv myenv
  • 安裝    pip install pyqt5
#第一個視窗hello world(ex1.py)
      1. import sys #只是為了使用在釋放程式的記憶體


      2. from PyQt5.QtWidgets import QApplication #qt的應用程式
      3. from PyQt5.QtWidgets import QLabel #qt的Label
      4. from PyQt5.QtWidgets import QWidget #qt的總部件,就是這個程式的視窗

      5. app QApplication(sys.argv#建立主程式的實體 app ,參數是一個list,如果不需要sys.argv,可以改成[]

      6. #以下一一建立程式中的顯示部件
      7. window QWidget() #建立視窗實體
      8. window.setWindowTitle('PyQt5 App'#視窗的抬頭
      9. window.setGeometry(20020028080#視窗的位置和大小(x,y,,)
      10. #window.move(6015#重新將視窗移到電腦螢幕的(60,15)位置
      11. helloMsg QLabel('<h1>Hello World!</h1>'parent=window#建立標籤實體,qt5接受html標籤
      12. helloMsg.move(6015#標籤移到視窗中的某位置

      13. window.show() #將視窗設定為顯示


      14. sys.exit(app.exec()) #開始執行應用程式,並在結束後,釋放記憶體。如果是python2,要用app.exec_()
p.s.載入要花一點時間,結果視窗關閉後,才能再回到命令列視窗。

#建立基本概念
  1. Widgets:各種部件
  2. Layout managers:排列部件的方式
  3. Dialogs:對話視窗
  4. Main windows:主視窗
  5. Applications:程式
  6. Event loops:監聽事件
  7. Signals and slots:事件發出的訊號(signals)和對應的處理程式(slots)。
1. 各種部件
  • Buttons:按鈕
  • Labels:多行文字
  • Line edits:單行文字
  • Combo boxes:下拉列表
  • Radio buttons:單選按鈕
......

2. 排列部件方式
  1. QHBoxLayout:水平排列容器 ex2.py
  2. QVBoxLayout:垂直排列容器 ex3.py
  3. QGridLayout:格狀排列容器 ex4.py

  4. QFormLayout:表單形式容器 ex5.py
3. 對話視窗(和主視窗彼此獨立,可以想成就是一般軟體裡跳出來,讓我們設定內容的視窗)--初學應該先學主視窗
特性:
對話視窗有2個內定的按鈕,「ok」、「cancel」。
有model 和 modeless 二種,model要用建class。
model 要用.exec()呼叫,modeless則是用.show()

這裡的範例是使用model的對話視窗 ex6.py
4. 主視窗  ex7.py
特性:
內定有功能列、工具列、狀態列等等的排列部件
一定要有中央部件,才有內容嘛
可以開出對話視窗來完成特定功能
5. 程式
在這裡,運用的是MVC架構,程式就是Control。它從view監聽接收資料,轉到model去,model做好資料的運算,再藉由Control,送到view顯示。

6. 監聽事件
一個無限的迴圈,時時看看有沒有哪個部件發出訊號了。就是.exec()的運作。
註:python2 使用.exec_(),python3 使用.exec()和.exec_()都可以。(因為python2自己內部有.exec())

7. 事件發出的訊號和對應的處理程式  ex8.py
訊號,如滑鼠按鍵或鍵盤被按下等等,代表某一個部件狀態改變了,需要處理程式來做出必要的處置。
它們之間的機制有
一個訊號,發給一個或多個處理程式。
一個訊號,連結到另外一個訊號。
一個處理程式,處理多個訊號。

python程式寫法,widget.signal.connect(slot_function)
ex7.py 中的程式,btn.clicked.connect(greeting) 當按鈕按下去(click),就執行greeting程式。
程式需要傳遞參數時,
在程式定義的部份,如同一般函數,將參數寫在(  )內,使用在字串之內時,用{  }。
在程式呼叫的部份,要使用functools.partial來間接呼叫。btn.clicked.connect(functools.partial(greeting,"world"))
p.s.使用functools,要先import functools。
請見 ex9.py

[ pyecharts ] 善用開放式資料,讀取股票交易資料,製作統計圖表

在2019年1月2日,我們以僅十行指令用某支股票的代碼來查詢某個月份的交易情形,其程式碼如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
import requests
import json
url = 'http://www.twse.com.tw/exchangeReport/STOCK_DAY?date=%s&stockNo=%s' % ( '20181201', '2892')
r = requests.get(url)
print(r.text)
data =json.loads(r.text)
print(data['title'])
print(data['fields'])
for row in data['data']:
    print(row)

2019年11月16曾介紹pyecharts套件的使用,在"初體驗! 使用pyecharts以水果交易行情為例"文章中,僅9行程式就能畫出台北一和台北二果菜場的交易,其程式如下:
from pyecharts.charts import Bar
from pyecharts import options as opts
from pyecharts.globals import ThemeType

bar = Bar(init_opts=opts.InitOpts(theme=ThemeType.LIGHT))

bar.add_xaxis(["椪柑", "蘋果 富士進口", "番石榴 珍珠芭", "香蕉", "木瓜 網室紅肉", "甜橙 柳橙", "火龍果 紅肉"])
bar.add_yaxis("台北一", [29.3, 51.5, 40.3, 21.6, 24.0, 61.5, 34.2])
bar.add_yaxis("台北二", [32.3, 51.4, 53.7, 24.7, 42.3, 23.4, 35.9])
bar.set_global_opts(title_opts=opts.TitleOpts(title="平均價", subtitle="元"))

bar.render()


我們把兩支程式合併,運用串列資料把股票交易日期當成x軸,再把開盤價、最高價、'最低價、以及'收盤價當成y軸來繪製圖表,其程式如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import requests
import json

url = 'http://www.twse.com.tw/exchangeReport/STOCK_DAY?date=%s&stockNo=%s' % ( '20181201', '2892')
r = requests.get(url)
print(r.text)
data =json.loads(r.text)

print(data['title'])
print(data['fields'])

price=data['fields'][3:7]
xaxis=[]
yaxis=[[],[],[],[]]

for row in data['data']:
    print(row)
    xaxis.append(row[0])
    for i, y in enumerate(yaxis):
        y.append(row[i+3])

from pyecharts.charts import Bar
from pyecharts import options as opts
from pyecharts.globals import ThemeType

bar = Bar(init_opts=opts.InitOpts(theme=ThemeType.LIGHT))

bar.add_xaxis(xaxis)
for i, y in enumerate(yaxis):
    bar.add_yaxis(price[i], y)

bar.set_global_opts(title_opts=opts.TitleOpts(title="平均價", subtitle="元"))

bar.render()

執行結果: