2018年5月23日 星期三

Python 學習筆記 : 資料庫存取測試: MySQL

Python 學習筆記 : 資料庫存取測試 (二) MySQL

MySQL 是目前後端網頁設計非常廣用的資料庫, 例如 XAMPP 就是整合 Apache, PHP 以及 MySQL 等工具在一體的網站開發套件, 如果有在用 XAMPP 開發 PHP 網站的話, 就不需要另外安裝 MySQL 給 Python 用, 只要啟動 XAMPP 中的 MySQL 伺服器即可, 還可以利用裡面的 phpMyAdmin 工具來瀏覽與手動管理資料庫.

我下載的是 XAMPP 可攜版, 只要解壓縮到 D 碟即可, 升版比較方便, 參考 :

# 安裝 XAMPP PHP 架站工具包

相對於內建的 SQLite 而言, Python 的 MySQL 連接方式書上介紹得比較少, 只在下列幾本書裡有提到 :

# Learning Python (Oreilly, Mark Lutz)
# 科學運算-Python 程式理論與應用 (第 16 章)

連接 MySQL 通常使用 MySQLdb 模組來驅動, 此模組在 GitHub 上的專案名稱為 mysql-python, 不過 MySQLdb 已經很老舊了 (已 12 歲), 僅支援 Python 2.x 且年久失修 (最近更新為 9 年前), 所以有人將其 fork 出來以支援 Python 3, 改名為 mysqlclient-python, 目前還有在持續更新, 作者希望將來能合併回 MySQLdb, 但看來是遙遙無期了. 參考 :

# 用Python 連接MySQL 的幾種方式
# Python3.x的mysqlclient的安装、Python操作mysql,python连接MySQL数据库,python创建数据库表,带有事务的操作,CRUD

本系列之前的測試文章如下 :

# Python 學習筆記 : 安裝執行環境與 IDLE 基本操作
# Python 學習筆記 : 檔案處理
# Python 學習筆記 : 日誌 (logging) 模組測試
# Python 學習筆記 : 資料庫存取測試 (一) SQLite

使用 MySQLdb 之前要先安裝 mysqlclient 模組 :

C:\Users\user>pip3 install mysqlclient
Collecting mysqlclient
  Downloading https://files.pythonhosted.org/packages/32/4b/a675941221b6e796efbb48c80a746b7e6fdf7a51757e8051a0bf32114471/mysqlclient-1.3.12-cp36-cp36m-win_amd64.whl (1.3MB)
Installing collected packages: mysqlclient
Successfully installed mysqlclient-1.3.12

安裝完成就可以匯入 MySQLdb 來連接 MySQL 資料庫了. 注意, 驅動程式雖然是 mysqlclient, 但模組名稱仍然是 MySQLdb, 不是 mysqlclient. MySQLdb 說明文件參考 :

# MySQLdb User’s Guide
# MySQLdb User's Guide (GitHub)
# Python - MySQL Database Access (Tutorials Point)
# https://dev.mysql.com/doc/refman/8.0/en/alter-table.html
# Python3 使用 mysqlclient 连接 MySQL / MariaDB
# Python 使用 MySQLdb 模組連接 MySQL 資料庫教學與範例
# 5.1 Connecting to MySQL Using Connector/Python


測試紀錄如下 :

1. 連線 MySQL 伺服器 :

連線 MySQL 伺服器須先匯入 MySQLdb 模組, 然後呼叫 connect() 並傳入 host (用 localhost 或 127.0.0.1 均可), user 以及 passwd 三個參數, 傳回值為一個 Conncection 連線物件 :

>>> import MySQLdb                             #匯入驅動模組
>>> conn=MySQLdb.connect(host="127.0.0.1",user="root", passwd="mysql")

呼叫連線物件之 cursor() 方法傳回一個 Cursor 物件, 呼叫其 execute() 方法並傳入 SQL 指令 "SELECT VERSION()" 再呼叫 fetchone() 或 fetchall() 方法可查詢資料庫版本訊息 :

>>> cursor=conn.cursor()     #傳回 Cursor 物件
>>> cursor.execute("SELECT VERSION()")     #查詢資料庫版本
1
>>> print("Database version : %s " % cursor.fetchone())
Database version : 10.1.28-MariaDB 

可見我這 XAMPP 使用的是與 MySQL 相容的 MariaDB. 注意, execute() 傳回 1 表示執行 SQL 指令成功, 傳回一筆紀錄.


2. 建立資料庫 :

接著執行 "CREATE DATABASE" 指令新建一個測試用的資料庫 testdb, 指定字元集 utf8 以支援中文 :

>>> SQL="CREATE DATABASE IF NOT EXISTS testdb DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_unicode_ci"
>>> cursor.execute(SQL) 
1
>>> conn.commit()              #操作結果寫入資料庫

傳回 1 表示 SQL 指令執行成功, 但所有更改資料庫的 SQL 操作結果只是實現於記憶體中, 需呼叫 Connection 物件的 commit() 方法才會真正寫入資料庫中.

按 XAMPP 控制台中, MySQL 的第二個按鈕 "Admin" 開啟 phpMyAdmin 網頁, 登入後切到 "資料庫" 頁籤即可看到多出一個新資料庫 testdb :





建好資料庫後, 可呼叫 close() 先關閉 Connection 物件與 Cursor 物件 :

>>> cursor.close()     #關閉 Cursor 物件
>>> conn.close()       #關閉 Connection 物件


3. 連接資料庫 :

接下來要再連線 MySQL 伺服器, 並傳入 db 與 charset 參數連接 testdb 資料庫, 利用傳回之 Connection 物件呼叫 cursor() 方法取得 Cursor 物件來操作資料庫 :

>>> conn=MySQLdb.connect(host="localhost",user="root", passwd="mysql", db="testdb", charset="utf8")                   #連線資料庫
>>> cursor=conn.cursor()           #傳回 Cursor 物件


4. 新增資料表 :

呼叫已指定資料庫之 Connection 物件之 execute() 方法執行 "CREATE TABLE" 即可新建資料表, 此處我們要建立一個名為 users 的資料表來儲存使用者資料, 包含 id, user_name, age, gender, password  等五個欄位 :

>>> SQL="CREATE TABLE IF NOT EXISTS users(id INT(5) \
... PRIMARY KEY AUTO_INCREMENT, user_name VARCHAR(20), \ 
... age TINYINT(3), gender CHAR(1),email VARCHAR(80), \
... password VARCHAR(20))" 
>>> cursor.execute(SQL)
0
>>> conn.commit()              #操作結果寫入資料庫

傳回 0 表示新增成功 (但沒有傳回任何紀錄), 否則會出現錯誤訊息. 在 phpMyAdmin 頁面顯示 users 資料表結構如下 :




MySQL 資料庫常用的欄位與其屬性如下 :

 欄位型態 說明
 VARCHAR(20) 可變長度字元 255 bytes (文字)
 CHAR(4) 固定長度字元 255 bytes (文字)
 TINYTEXT 255 Bytes (文字)
 TEXT 65535 bytes (文字)
 MEDIUMTEXT 16777215 bytes (文字)
 LONGTEXT 4294967295 bytes (文字)
 TINYBLOB 255 bytes (文字)
 BLOB 65535 bytes (文字,分大小寫)
 MEDIUMBLOB 16777215 bytes (文字,分大小寫)
 LONGBLOB 4294967295 bytes (文字,分大小寫)
 TINYINT(M) 1 bytes (最大顯示寬度 M<=255)
 SMALLINT(M) 2 bytes (最大顯示寬度 M<=255)
 MEDIUMINT(M) 3 bytes (最大顯示寬度 M<=255)
 INT(M),INTEGER(M) 4 bytes (最大顯示寬度 M<=255)
 BIGINT(M) 8 bytes (總位數 M<=65, 小數位數 D<=30&M-2)
 FLOAT(M,D) 4 bytes (總位數 M<=65, 小數位數 D<=30&M-2)
 DOUBLE(M,D) 8 bytes (總位數 M<=65, 小數位數 D<=30&M-2)
 DECIMAL(M,D) ? bytes (總位數 M<=65, 小數位數 D<=30&M-2)
 DATE 3 bytes (YY-MM-DD)
 DATETIME 8 bytes (YY-MM-DD HH:MM::SS)
 TIMESTAMP 4 bytes (1970-01-01 00:00:00)
 TIME 3 bytes (HH:MM:SS)
 YEAR(2|4) 1 byte (預設 4)
 ENUM 1~2 bytes (儲存單選 radio)
 SET 1~8 bytes (儲存多選 checkbox)

而屬性是放在類型後面的限制, 如下表所示 :

 屬性 說明
 SIGNED,UNSIGNED 是否有負值 (數值)
 AUTO_INCREMENT 自動增量編號 (數值)
 BINARY 字元有大小寫之分 (文字)
 NULL,NOT NULL 是否允許不填入資料 (全部)
 DEFAULT 預設值
 PRIMARY KEY 資料表之唯一主鍵


5. 新增與查詢紀錄 : 

新增紀錄之 SQL 指令為 "INSERT INTO", 可呼叫 Cursor 物件之 execute() 與 executemany() 分別新增一筆或多筆紀錄, 例如 :

>>> SQL="INSERT INTO users(user_name,age,gender,email,password) VALUES('愛咪','12','女','amy@gmail.com','123')"     #新增紀錄
>>> cursor.execute(SQL) 
1
>>> conn.commit()                     #操作結果寫入資料庫

傳回 1 表示插入一筆紀錄成功, 可用 "SELECT" 指令查詢資料表, 傳回之紀錄集可用 Cursor 物件之 fetchone(), fetchall(), 或 fetchmany(n) 等方法以串列型態傳回 :

>>> SQL="SELECT * FROM users"       #查詢資料表
>>> cursor.execute(SQL) 
1
>>> print(cursor.fetchone())                       #擷取紀錄集
(1, '愛咪', 12, '女', 'amy@gmail.com', '123')
>>> print(cursor.fetchone())                       #擷取紀錄集
()

每呼叫一次 fetchone() 游標就指向下一個紀錄集, 因為目前 users 內只有一筆紀錄, 因此第二次呼叫時傳回空的 tuple. 呼叫 executemany() 可一次插入多筆紀錄, 例如 :

>>> SQL="INSERT INTO users(user_name,age,gender,email,password) VALUES(%s, %s, %s, %s, %s)"
>>> cursor.executemany(SQL, [('彼得',14,'男','peter@gmail.com','456'),\
... ('凱莉',16,'女','kelly@gmail.com','789')]) 
2
>>> conn.commit()              #操作結果寫入資料庫

傳回 2 表示插入 2 筆紀錄成功. 此處 SQL 指令的 VALUES 部分以 %s 格式代表要插入的各欄位值, 注意, 不管是數值或字串都用 %s, 數值若用 %d 會報錯. 多筆紀錄以串列型態傳入 executemany() 的第二參數中, MySQLdb 模組會自動抽出每一筆紀錄插入 SQL 指令的 %s 格式中.

>>> SQL="SELECT * FROM users"        #查詢資料表
>>> cursor.execute(SQL)
3
>>> cursor.fetchall()                                      #擷取紀錄集 (全部)
((1, '愛咪', 12, '女', 'amy@gmail.com', '123'), (2, '彼得', 14, '男', 'peter@gmail.com', '456'), (3, '凱莉', 16, '女', 'kelly@gmail.com', '789'))

可見 fetchall() 可擷取目前 users 內全部 3 筆紀錄. 還可用 fetchmany(n) 傳入要擷取的紀錄筆數, 但須再查詢一次 :

>>> cursor.execute(SQL)                              #重新查詢資料表
3
>>> cursor.fetchmany(2)                              #擷取 2 筆紀錄
((1, '愛咪', 12, '女', 'amy@gmail.com', '123'), (2, '彼得', 14, '男', 'peter@gmail.com', '456'))
>>> cursor.fetchmany(3)                              #擷取 3 筆紀錄
((3, '凱莉', 16, '女', 'kelly@gmail.com', '789'),)


6. 更新紀錄 : 

更新紀錄使用 "UPDATE" 指令, 在此之前我們先插入一筆資料不全的紀錄 ;

>>> SQL="INSERT INTO users(user_name) VALUES('東尼')"
>>> cursor.execute(SQL)                            #新增紀錄
1
>>> conn.commit()                                      #操作結果寫入資料庫
>>> SQL="SELECT * FROM users"      #查詢資料表
>>> cursor.execute(SQL) 
4
>>> cursor.fetchall()                                    #擷取全部紀錄
((1, '愛咪', 12, '女', 'amy@gmail.com', '123'), (2, '彼得', 14, '男', 'peter@gmail.com', '456'), (3, '凱莉', 16, '女', 'kelly@gmail.com', '789'), (4, '東尼', None, None, None, None))

可見資料不全的欄位值均為 None. 使用 "UPDATE" 指令來補全這筆紀錄闕漏之欄位 :

>>> SQL="UPDATE users SET age='48',gender='男',email='tony@gmail.com', password='abc' WHERE user_name='東尼'"      
>>> cursor.execute(SQL)                           #更新紀錄
1
>>> conn.commit()                                     #操作結果寫入資料庫
>>> SQL="SELECT * FROM users"     #查詢資料表
>>> cursor.execute(SQL) 
4
>>> cursor.fetchall()                                   #擷取全部紀錄
((1, '愛咪', 12, '女', 'amy@gmail.com', '123'), (2, '彼得', 14, '男', 'peter@gmail.com', '456'), (3, '凱莉', 16, '女', 'kelly@gmail.com', '789'), (4, '東尼', 48, '男', 'tony@gmail.com', 'abc'))     

可見欄位資料已補全.


7. 刪除紀錄 :

>>> SQL="DELETE FROM users WHERE id='4'"
>>> cursor.execute(SQL)                             #刪除紀錄
1
>>> conn.commit()                                       #操作結果寫入資料庫
>>> SQL="SELECT * FROM users"       #查詢資料表
>>> cursor.execute(SQL) 
3
>>> cursor.fetchall()                                     #擷取全部紀錄
((1, '愛咪', 12, '女', 'amy@gmail.com', '123'), (2, '彼得', 14, '男', 'peter@gmail.com', '456'), (3, '凱莉', 16, '女', 'kelly@gmail.com', '789'))

可見最後一筆已被刪除剩下 3 筆.


8. 更改資料欄位 :

更改資料欄位使用 "ALTER TABLE" 指令, 包括新增欄位與更改欄位型態. 與 SQLite 一樣必須一個一個欄位執行, 例如新增 telephone 與 city 兩個欄位 :

>>> SQL="ALTER TABLE users ADD telephone CHAR(20)"   #新增欄位
>>> cursor.execute(SQL)
4
>>> SQL="ALTER TABLE users ADD city CHAR(20)"             #新增欄位
>>> cursor.execute(SQL)
4
>>> conn.commit()
>>> SQL="INSERT INTO users(user_name) VALUES('潔西卡')"   #新增紀錄
>>> cursor.execute(SQL)
1
>>> SQL="SELECT * FROM users"     #查詢全部紀錄
>>> cursor.execute(SQL)
5
>>> cursor.fetchall()
((1, '愛咪', 12, '女', 'amy@gmail.com', '123', None, None), (2, '彼得', 14, '男', 'peter@gmail.com', '456', None, None), (3, '凱莉', 16, '女', 'kelly@gmail.com', '789', None, None), (4, '東尼', 48, '男', 'tony@gmail.com', 'abc', None, None), (5, '潔西卡', None, None, None, None, None, None))

可見新增的欄位值均為 None.

更改欄位型態需用 "ALTER TABLE table MODIFY field type" 指令, 例如要將 email 欄位從原先的 VARCHAR(80) 加上 NOT NULL 屬性 (即新增紀錄時一定要給值), 其 SQL 指令為 :

SQL="ALTER TABLE users MODIFY email VARCHAR(80) NOT NULL"

注意, 因為 NOT NULL 只是屬性, 必須伴隨類型 VARCHAR(80) 才能修改, 例如 :

>>> SQL="ALTER TABLE users MODIFY email CHAR(80) NOT NULL"
>>> cursor.execute(SQL)
__main__:1: Warning: (1265, "Data truncated for column 'email' at row 5")
5
>>> conn.commit()

進入 phpMyAdmin 查詢 testdb 資料表結構可知 email 欄位的 NULL 已經不見了 :




如果只改欄位類型, 例如將 VARCHAR(80) 改為 VARCHAR(100) :

>>> SQL="ALTER TABLE users MODIFY email CHAR(100)"
>>> cursor.execute(SQL) 
5
>>> conn.commit()

這樣字串長度雖然放寬至 100, 但上面添加的 NOT NULL 會消失不見 :




因此在使用 MODIFY 修改欄位型態與屬性時, 還要繼續保持之屬性一定要列入, 否則會被刪除.

更改欄位名稱要用 "ALTER TABLE table CHANGE COLUMN" 指令, 例如將 email 欄位名稱改為開頭大寫的 Email :

>>> SQL="ALTER TABLE users CHANGE COLUMN email Email VARCHAR(70)"
>>> cursor.execute(SQL)
4

注意, 雖然只是要改欄名, 但欄位的定義不可省略, 否則會報錯. 更多 ALTER TABLE 指令參考 :

# https://dev.mysql.com/doc/refman/8.0/en/alter-table.html


參考 :

# [MySQL]Python連結MySQL---查詢篇
# GitHub 上 Fork、Watch、Star 是什麼意思?
# 5.1 Connecting to MySQL Using Connector/Python
# mysql-connector-python-8.0.11-py3.6-windows-x86-64bit.msi
# https://dev.mysql.com/downloads/file/?id=477196
# Download MySQL connector for Windows 64-bit
# 5.1 Connecting to MySQL Using Connector/Python


2018-05-06 補充 :

為了重複測試方便, 不用再手動一行一行輸入, 我將資料表 users 輸出為 .sql 檔備份, 內容如下 :

-- phpMyAdmin SQL Dump
-- version 4.8.0
-- https://www.phpmyadmin.net/
--
-- 主機: 127.0.0.1
-- 產生時間: 2018-05-06 01:34:50
-- 伺服器版本: 10.1.31-MariaDB
-- PHP 版本: 7.2.4

SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
SET AUTOCOMMIT = 0;
START TRANSACTION;
SET time_zone = "+00:00";


/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8mb4 */;

--
-- 資料庫: `testdb`
--

-- --------------------------------------------------------

--
-- 資料表結構 `users`
--

CREATE TABLE `users` (
  `id` int(5) NOT NULL,
  `user_name` varchar(20) COLLATE utf8_unicode_ci DEFAULT NULL,
  `age` tinyint(3) DEFAULT NULL,
  `gender` char(1) COLLATE utf8_unicode_ci DEFAULT NULL,
  `email` varchar(80) COLLATE utf8_unicode_ci DEFAULT NULL,
  `password` varchar(20) COLLATE utf8_unicode_ci DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

--
-- 資料表的匯出資料 `users`
--

INSERT INTO `users` (`id`, `user_name`, `age`, `gender`, `email`, `password`) VALUES
(1, '愛咪', 12, '女', 'amy@gmail.com', '123'),
(2, '彼得', 14, '男', 'peter@gmail.com', '456'),
(3, '凱莉', 16, '女', 'kelly@gmail.com', '789'),
(4, '東尼', 48, '男', 'tony@gmail.com', 'abc');

--
-- 已匯出資料表的索引
--

--
-- 資料表索引 `users`
--
ALTER TABLE `users`
  ADD PRIMARY KEY (`id`);

--
-- 在匯出的資料表使用 AUTO_INCREMENT
--

--
-- 使用資料表 AUTO_INCREMENT `users`
--
ALTER TABLE `users`
  MODIFY `id` int(5) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=5;
COMMIT;

/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;


以下是手動執行指令 :

SQL="CREATE TABLE IF NOT EXISTS users(id INT(5) PRIMARY KEY AUTO_INCREMENT, user_name VARCHAR(20), age TINYINT(3), gender CHAR(1),email VARCHAR(80),  password VARCHAR(20))"

cursor.execute(SQL)

SQL="INSERT INTO users(user_name,age,gender,email,password) VALUES(%s, %s, %s, %s, %s)"

cursor.executemany(SQL, [('愛咪','12','女','amy@gmail.com','123'),('彼得',14,'男','peter@gmail.com','456'), ('凱莉',16,'女','kelly@gmail.com','789'), ('東尼', 48, '男', 'tony@gmail.com', 'abc')])

2018年5月15日 星期二

從三國演義__學Scratch程式


【轉寄好友】【友善列印】推到   推到 
  【免費加入會員】  【學員須知】【常見問題】
【課程名稱】從三國演義學Scratch程式 
【課程代碼】07Q024
【上課時間】2018/7/16(一)、7/17(二)、7/18(三),9:00~16:00,共18小時 
【課程目標】1.認識Scratch
2.透過歷史學程式
3.學會事件驅動、循序程式與音效剪輯
4.學會物件導向與訊息傳遞
5.學會按鈕操作與有限回圈
6.學會滑鼠拖動、簡易變量與條件迴圈
7.學會按鍵操作與條件恤數
8.學會數值變量
【修課條件】國小三年級~國中一年級
【課程大綱】1.桃園三結義
1.1認識scratch─我的第一首有聲詞
1.2大家說故事─桃園三結義
1.3我的第一部動畫─人物對話
2.煮酒論英雄
2.1大家說故事─煮酒論英雄
2.2我的第二部動畫(一)─場景變換
2.3我的第二部動畫(二)─音效剪輯
3.過五關斬六將
3.1大家說故事─過五關斬六將
3.2我的第一支遊戲(一)─按鈕操作
3.3我的第一支遊戲(二)─有限迴圈
4.三顧茅廬
4.1大家說故事─三顧茅廬
4.2我的第二支遊戲(一)─簡易變數
4.3我的第二支遊戲(二)─條件迴圈
5.張飛橫斷長板橋
5.1大家說故事─張飛橫斷長板橋
5.2我的第三支遊戲(一)─人物控制
5.3我的第三支遊戲(二)─條件敘述
6.草船借箭
6.1大家說故事─草船借箭
6.2我的第四支遊戲(一)─簡易公式
6.3我的第四支遊戲(二)─數值變量
【課程師資】1.台北科技大學-暑期營隊老師。
2.中原大學推廣教育處-暑期營隊老師。
3.桃園成功國小百變創意機器人、機甲戰車-社團老師。
4.桃園建德國小百變機器人、戰鬥科學營-社團老師。
5.桃園大成國小創意機器人-社團老師。
6.桃園東勢國小創意機器人-社團老師。
7.桃園大業國小迷走車、創意積木-社團老師。
【上課時數】18 小時
【上課地點】台北分部(台北市博愛路80號3樓)
【課程費用】4500元 (超值優惠價格需送出報名表後,系統發出報名成功回函確認金額。)
【超值優惠】
  • VIP企業會員價:VIP企業會員可享優惠價格 (按我)
  • 會員優惠價: 會員於開課前七天完成報名繳費者可享會員優惠價 4300 元
【諮詢專線】02-23113316分機2282 林小姐 hllin@tcfst.org.tw
【學員須知】報名與繳退費方法| 常見問題與解決|會員紅利積點活動辦法
【注意事項】
  1. 若遇不可預測之突發因素,基金會保有相關課程調整、取消及講師之變動權。
  2. 無紙化環境,輕鬆達到減碳救地球,即日起16小時以上課程結業證書改以電子方式提供。
  3. 使用VIP廠商優惠之學員,上課當日報到時須查核該公司識別證(相關證明資料)。
  4. 課前請詳閱簡章之課程內容或利用課程諮詢電話。
  5. 課程嚴禁旁聽,亦不可攜眷參與。
101.12.162.132


PS.  
http://scratch.gdps.ntpc.edu.tw/

2017年9月20日 星期三

幼童教育_學思達...

十全國小李笙帆老師觀課心得

觀課日期:107.9.19週二上午
觀課老師:十全國小李笙帆
授課老師:英明國中郭進成



感謝進成老師願意開放教室,讓我和教學夥伴一同進入班級觀課,雖然素昧平生,但老師仍然很親切地與我們議課交流。

看著學生在老師的帶領下,漸漸習慣「自學」的態度、培養「思考」的能力及愈漸成熟的「表達」,這都不是一蹴可幾的,然而,在老師的堅定下,就是能夠達成這樣的目標。

今天,我感受到了「學思達」的魅力,翻轉教室的能量,更重要的是看到在教育現場辛苦耕耘、不斷精進的超級優秀老師----您。

這難忘而寶貴而受用無窮的經驗,將為我帶來成長,進而回饋給自己的學生,謝謝您的指導,以下是我的觀課回饋。

一、收穫
(一) 課前備課編製引導單:
老師事先設計引導單,讓學生能夠事先預習,且讓上課能夠更加聚焦重點。引導單根據學思達的精神、閱讀理解策略及會考重概念來進行編製,以素養、能力為導向的問題意識引導單,確實能幫助學生學習理解。



(二) 學生討論時,教師各組巡視協助:
老師在指導課堂討論時,能夠幫助較弱勢的同學,甚至會直接坐在學生旁邊給於協助;老師也能兼顧各組,讓大家都能回到問題本身,翻看課本進行檢閱、討論、理解。

有些學習動機較薄弱的學生因為同儕的影響,也會願意打起精神來思考討論。

(三) 善用「計時器」:
老師運用「計時器」,不僅能掌握課堂時間、節奏,更能幫助學生在有限的時間內進行討論學習。

(四) 抽問技巧:(隨機抽問、重點抽問、快問快答)
當各組討論出答案時,老師會讓各組「亮牌」(組長把白板拿起來給大家看),接著讓幾個小組回答,若有不同答案的,也會再讓學生說明澄清。

此外,在各組討論過後,或是老師歸納重點後,老師也會隨機抽點同學回答、快問快答加分,讓所有的同學都能聚精會神學習。

(五)教學策略:(作筆記、畫重點、找關鍵詞、畫樹狀圖、歸納重點……)

在課堂中,老師會教學生學習閱讀策略,在這堂課中,我看到了老師教學生分辨「T圖」、「T表」及畫「樹狀圖」……等,老師也在引導單上刻意畫出不同的歸納圖,讓學生不能只是抄寫,而是要自己理解吸收後才能寫出來。

而「畫重點」這工作,不是老師用念的,是讓學生自己整理、歸納出重點後才畫下來,真的有效培養學生「思辨」的能力。

老師請學生用「一個最精簡的詞」來說明、分辨民主和獨裁政體,有學生提出:主權在民、民意監督……等,老師最後並沒有要求學生一定要寫哪一個,而是告訴學生自己決定筆記,要自己看得懂、能了解的,這能夠將學習的責任回歸到學生身上,這樣的引導技巧非常好,也讓人驚艷。

老師引導學生把「標題縮短」(找關鍵字),原本的四字標題到最後聚焦在兩個字,學生學會抓重點,幫助歸納理解。

(六)學生發表,老師釋疑
學生發表時,老師會比較各組的異同,如果是討論失焦的小組,老師會請學生再次解說,若還是無法理解,在不影響班級課程進行下,會在下課後留下來個別解說,老師盡可能澄清學習迷思。

在同學發表時,老師會說「請大家看著某某同學」,這樣的提醒是很好且必要的。

(七)分組競賽,個別增強
老師運用分組競賽的方式,可以讓小組成員互助合作,彼此激勵;個人回答問題也能得到加分的機會。老師拿具體的「增強牌」加分,是很好的方式。若整組沒有得到六分,必須留下來擦桌子,這也可以提醒學生認真學習。

(八)柔軟而堅定的課堂管理
在課堂中,並不是所有的學生都能有效學習,有的學生甚至會說一些題外話,但老師能夠有好的回應,讓學生在課堂中有安全感,而老師也能管理班級秩序。老師所下的指令都是溫柔而堅定的,會要求而徹底執行,學生因為老師的關懷用心而更願意努力學習。

(九)老師統整歸納重點
在課堂上,雖然大部分的時間是學生自學、討論,但需要澄清重點時,老師會歸納釐清,例如在看一張重點圖表時,老師請學生「手指著圖」,這樣的教學策略可以讓學生更專心、理解重點。

二、疑惑
(一)「引導單」的使用時機?
今天有向老師提出「引導單」使用時機的疑惑,老師說明一個單元製作一張引導單,用共備的方式產出。引導單的設計力求「精簡聚焦」,必須要刪除次要的資訊,幫助學生學習重點;也要以「能力素養」為主軸來設計,培養學生自學的能力。

「引導單」是在課前發下,每次上課都要和課本一起帶著,有許多同學都是直接夾在課本裡,老師上課會搭配使用。

(進成案:課堂引導單的設計,很感謝有公民共備社群夥伴的協助才能產出,讓我知道許多學習弱勢學生的需求,許多課堂的常規問題,很可能就是因為這些學生無法參與課堂所導致。如果學生根本看不懂教科書,如何自學呢?當我覺察到這一點,決定開始將閱讀理解策略放進課程當中,幫助這些學生。目前已經看到一些令人驚喜的改變。)

(二)「板書」使用較少?
在老師的課堂,很少使用板書,學生是將討論的結果寫在白板上作答,而整堂課也以學生自學討論居多,因此板書使用自然少。

(三)是否因各班學習風氣不同而影響成效
每個班級的學習風氣不同,會不會有班級無法使用「學思達」來進行教學。老師認為是不會影響的,首先是老師有清楚說明要求規定,並徹底執行;此外,這樣開放討論的課程,反而有助於學習動機低落的孩子,因為同儕間會互相學習影響。

三、建議
真的不敢給老師建議,以下提供我的淺見當作參考:
(一)是否讓學生站起來回答?
在2016海峽兩岸教學觀摩會時,會中有老師提出疑義,就是大陸的老師會要求學生站起來回答,而台灣的老師則不會要求,因此學生習慣坐著回答。這個議題在當時會議中引起滿大的討論。

我自己經過思考後,認為「站著回答問題」不是要尊師重道的優越感,更重要的是學生站起來回答問題時會更加謹慎專心,因此,經過海峽兩岸觀摩會後,我開始會要求學生站起來回答問題。我並不是所有的問題都要求起立回答,如果個人簡短的生活經驗發表,坐著就可以;如果是經過整組討論後的重要發表,我就會要求學生起立回答或上台發表。
這點可以提供老師參考。

(進成案:謝謝你的提醒,未來會試著這麼做。)

(二)要求學生回答「完整的句子」:
在學生回答問題或發表時,我發現有些學生沒有用完整的句子,會缺少「主語」。建議老師可以參考溫美玉老師開發的「觀點卡」(我認為…因為…、我的觀點是…因為…、我質疑…因為…、我推斷…因為…、我同意…因為…、我不同…因為…意、我預測…因為…),用這樣的方式或許可以鷹架學生的發表。

(進成案:很棒的建議,很受用。)
    
(三)下課時說「謝謝老師」:
 老師教學認真又辛苦,建議老師說「下課」後,讓同學回應「謝謝老師」,同學可以不必制式化的站起來行禮,但可以讓學生學習到感恩感謝。

2016年4月25日 星期一

VMware Workstation-11


Workstation是功能強大的虛擬機軟件: 

與VMware的vCloud虛擬航空私有雲整合
通過連接到vCloud航和上載,運行和查看虛擬機從工作站11接口,外部雲,你現在可以延長和擴展您的虛擬機。
支持使用 EFI 啟動虛擬機
創建虛擬機的桌面快捷方式
序號:1F04Z-6D111-7Z029-AV0Q4-3AEH8

2015年8月28日 星期五

Linux 學習單元



在CentOS中安装gcc配置 C语言开发环境




  1. 先進入資料庫,執行以下SQL語法(xx_modules請自行替換正確的前置字串):
    INSERT INTO `xx_modules` ( `name`, `version`, `last_update`, `weight`, `isactive`, `dirname`, `hasmain`, `hasadmin`, `hassearch`, `hasconfig`, `hascomments`, `hasnotification`) VALUES
    ('站長工具箱', 255,  1412347040, 0,  1,  'tad_adm',  1,  1,  0,  1,  0,  0);
  2. 接著觀察「站長工具箱」的模組編號,即mid的值,並在下方語法填入正確mid數字,接著再執行:
    INSERT INTO `前置字串_group_permission` (`gperm_groupid`, `gperm_itemid`, `gperm_modid`, `gperm_name`) VALUES
    (1,  mid的值,  1,  'system_admin'),
    (1,  mid的值,  1,  'block_read'),
    (1,  mid的值,  1,  'module_admin'),
    (1,  mid的值,  1,  'module_read'),
    (2,  mid的值,  1,  'module_read'),
    (3,  mid的值,  1,  'module_read');