目前分類:Python 程式設計 (52)

瀏覽方式: 標題列表 簡短摘要

HTTP Status 狀態代表的意思

瀏覽器接收到伺服器的回應後,都會自動去判讀網頁的狀態,其中的 Http Status代碼的意思如下:

最簡單狀態碼如下:

  • 1xx訊息: 這一類型的狀態碼,代表請求已被接受,需要繼續處理。
  • 2xx成功: 這一類型的狀態碼,代表請求已成功被伺服器接收、理解、並接受。
  • 3xx重新導向: 這類狀態碼代表需要用戶端採取進一步的操作才能完成請求。通常,這些狀態碼用來重新導向, 
  • 4xx用戶端錯誤: 這類的狀態碼代表了用戶端看起來可能發生了錯誤,妨礙了伺服器的處理。
  • 5xx伺服器錯誤: 表示伺服器無法完成明顯有效的請求。]這類狀態碼代表了伺服器在處理請求的過程中有錯誤或者異常狀態發生,也有可能是伺服器意識到以當前的軟硬體資源無法完成對請求的處理。

簡單狀態碼如下:

  • 200 伺服器回應Data成功。
  • 206 取得片段資料,Http Request 中有的 Range 屬性,可以指定要取得那一段Bytes數。
  • 301 目標網頁移到新網址(永久轉址)。
  • 302 暫時轉址
  • 304 已讀取過的圖片或網頁,由瀏覽器緩存 (cache) 中讀取。
  • 401 需身分驗證,如 SSL key  or htaccess pasword。
  • 403 沒有權限讀取,可能是 IP 被阻檔或是伺服器限制。
  • 404 伺服器未找到目標網址,檔案不存在。
  • 408 Client Request  timeout
  • 411 沒有指定  content-length,使用 POST 傳送參數時,必須指定參數的總長度
  • 414 URL 太長導致伺服器拒絕處理。
  • 500 伺服器發生錯誤 : 可能是 htaccess 有錯
  • 503 伺服器當掉 : maybe is code dump
  • 505 不支此 HTTP 版本

 更多狀態碼如下:

https://zh.wikipedia.org/zh-tw/HTTP%E7%8A%B6%E6%80%81%E7%A0%81

回Django Web 程式設計主目錄

文章標籤

stanley 發表在 痞客邦 留言(0) 人氣()

 

Django Web 程式設計目錄列表

 

Django 筆記(一)-Hello World 

Django 筆記(二)-Views & Templates

Django 筆記(三)-Models & Database 

Django 筆記(四)-總結記錄

HTTP Status 狀態列表及說明 

HTTP Request 方法: Get 和 Post

Django 筆記(五)-Django遇見Javascript和JQuery

Django 筆記(六)- Templates深入研究 

 

參考文件:

(1) w3schoolds : https://www.w3schools.com/

 

 

 

文章標籤

stanley 發表在 痞客邦 留言(0) 人氣()

  2017.08.25 

在上三篇文章中我們己經使用了URLS、Templates、 Views、Models及Database所有元件,這篇我們記錄一個最基本的範例程式,這個程式連結所有的元件,從使用者Reguest資料到資料表內容呈現到瀏覽器上。我們只使用一個簡單的資料表,而使用者的需求為列出資料表的內容。這個記錄不再作過多的文字說明,有問題請回主目錄點選以前的文件說明。


開啓Web Service  
     開啓一個CMD視窗,切換路徑到專案manage.py 所在目錄,執行

python manage.py runserver

程式範例

在urls.py

from django.conf.urls import include, url
from django.contrib import admin
from kaok.views import list

urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),
    url(r'^list/$', list),
]

在models.py

from django.db import models

class kaok(models.Model):
    song_no = models.CharField(max_length=6)
    songer = models.CharField(max_length=30)
    song_name = models.CharField(max_length=60)
    song_lang = models.CharField(max_length=20)
    song_kind = models.CharField(max_length=20)
    song_words = models.CharField(max_length=3)

在views.py  

from django.shortcuts import render
from django.template.loader import get_template
from django.http import HttpResponse
from kaok.models import kaok


def list(request):
    data = kaok.objects.all()   
    return render(request, 'list.html',{'datas':data})

在 /templates下新增 list.html 


<!doctype html>
<html>
    <head>
    </head>
    <body>資料表內容<br>
     {% for item in datas %}
      <tr>
        <td>{{ item.song_name }}</td>       
        <td>{{ item.songer }}</td>
      </tr><br>
     {% endfor %}
    </body>
</html>

 在瀏覽器輸入 http://127.0.0.1:8000/list,可以看到頁面如下

Django

有這個程式範例我們後續就可以再發展比較複雜的Web程式了。

回Django Web 程式設計主目錄

 

 

 

文章標籤

stanley 發表在 痞客邦 留言(0) 人氣()

 2017.08.24 

資料來源: (1)https://djangobook.com/the-django-book/

      在上二篇文章中我們己經使用了URLS、Templates、 Views,這篇文章我們將介紹Models設定及Database的使用,並且整合之前的元件,我們仍舊要從到我們的MTV架構開始談起,為什麼呢,我個人覺得這個圖及架構就是Django的設計精神,有些設定及設計流程要思考這個圖就能理解一大半了。從圖中可以看到Models介於Views及資料庫之間,如果我們不要Models 層將資料庫設定及資料全放在Views是否可以,聰明的你一定猜到了,從下圖的資料訊流顯示那一定是可以的,是否有這種的設計方式呢,當然是有像傳統的網頁設計就是使用這樣的架構設計,他們不用管什麼三層式架構,資料層,企業邏輯層,資料呈現層全部混在一起全部放在一個檔案內,這種方式當然也是可以的。而這種方式目前在市場上也是佔有一席之地的。為什麼呢? 因為全部程式使用的元件比較少,整個架構及流程設計會比較簡單。但後續程式的維護修改會比較有問題。那就是當換資料庫時全部有關係到資料庫設定的Views就要全部都翻過一次。

(資料來源:http://blog.easylearning.guru/implementing-mtv-model-in-python-django/)

 回到Models的問題,我可以先破題的說Models 記錄的內容就是tables 及tables之間關連性的內容。記住這字話後面的內容設定,程式設計將會變的簡單。

資料庫設定


首先我們先開啓一個資料庫,以供後面的Models及程式用
打開 settings.py檔案,預設資料庫是sqlite
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}

我們使用預設資料庫,所以不做任何異動,你可以依你的資料庫類型改變設定。另外在settings.py內尋找
INSTALLED_APPS ,把你的app name 加入,讓Django知道那些是我們會有到的app。
例如我想要設計一個KTV 點歌的web app,所以我加入了kaok 到settings.py內。如果其他預設的app 不需要可以加上#

 

INSTALLED_APPS = (
    #'django.contrib.admin',
    #'django.contrib.auth',
    #'django.contrib.contenttypes',
    #'django.contrib.sessions',
    #'django.contrib.messages',
    #'django.contrib.staticfiles',
    'kaok',
)


定義Django Models內容

from django.db import models

class kaok(models.Model):
    song_no = models.CharField(max_length=6)
    songer = models.CharField(max_length=30)
    song_name = models.CharField(max_length=60)
    song_lang = models.CharField(max_length=20)
    song_kind = models.CharField(max_length=20)
    song_words = models.CharField(max_length=3)

我們的例子比較簡單,只有一個Model 和 數個文字型態的欄位,在這個地方你可以把Model物件=table。
(1)Model 物件名字就是table名字。
(2)定義欄位名、欄位型態、最大長度。(其他欄位型態我們例子没用到,請看下面比較複雜的範例)
(3)定義Models之間的關連性(我們例子没用到,請看下面比較複雜的範例)

from django.db import models

class Publisher(models.Model):
    name = models.CharField(max_length=30)
    address = models.CharField(max_length=50)
    city = models.CharField(max_length=60)
    state_province = models.CharField(max_length=30)
    country = models.CharField(max_length=50)
    website = models.URLField()   #URL欄位型態

class Author(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=40)
    email = models.EmailField()  #Email欄位型態

class Book(models.Model):
    title = models.CharField(max_length=100)
    authors = models.ManyToManyField(Author) # book 有1對多 authors 關係
    publisher = models.ForeignKey(Publisher) # 它是一個Publisher的ForeignKey
    publication_date = models.DateField() #日期欄位型態

更多欄位型態訊息請參考https://www.webforefront.com/django/modeldatatypesandvalidation.html
更多模式關係訊息請參考https://www.webforefront.com/django/setuprelationshipsdjangomodels.html


產生資料庫內容

 一但我們建立了model, 我們須要去建立新的或更新舊資料庫table內容,所以執行下面指令

python manage.py syncdb

 

系統會開始建立table, 如果是第一次執行系統會依INSTALLED_APPS 的內容開始產生table和一個superuser

Creating tables ...
Creating table django_admin_log
Creating table auth_permission
Creating table auth_group_permissions
Creating table auth_group
Creating table auth_user_groups
Creating table auth_user_user_permissions
Creating table auth_user
Creating table django_content_type
Creating table django_session
Creating table kaok_kaok

You just installed Django's auth system, which means you don't have any superuse
rs defined.
Would you like to create one now? (yes/no):yes
Username (leave blank to use 'XXX'): root
Email address: XXXX@gmail.com
Password:
Password (again):
Superuser created successfully.
Installing custom SQL ...
Installing indexes ...
Installed 0 object(s) from 0 fixture(s)

假如你有異動INSTALLED_APPS 的內容,請再次執行 syncdb 以同步資料庫內容。
系統會在專案目錄下產生一個 db.sqlite3檔案。

 

與Model互動

當table 建立後你可能須要對table內容對S(查詢)、I(插入)、D(刪除)、U(更新),你可以利用指令去完成資料的操縱,或者你也可以用後面Admin介面去操控資料,更或者你可以使用熟悉的資料庫管理工具應該也可以操控資料,所以有興趣可以找一下其他資料。

python manage.py shell

 

Admin介面

amin是Djanog中內建的一個app,如果你没有移除它的話相信你在建table時就會看到它的table了。

要使用Admin介面要新增註冊資料至Admin.py,新增內容如下

 

from django.contrib import admin
from .models import kaok
admin.site.register(kaok)

 在瀏覽器輸入 http://127.0.0.1:8000/admin,可以看到管理後台的登入頁面:

如剛才無設定superuser,請用下指令新增

python manage.py createsuperuser

其他資料庫管理工具
  
我也下載了其他的資料庫管理工具,SQLiteStudio 事實證明使用其他的工具也是操縱所有的資料表內容。我利用這個軟體新增了二筆資料以作做後續程式測試使用。

回Django Web 程式設計主目錄

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

文章標籤

stanley 發表在 痞客邦 留言(0) 人氣()

 2017.08.22 

資料來源: (1)https://djangobook.com/the-django-book/

Django Templates

      在上篇文章中我們己經成功了呈現了字串"Hello World",簡單地說我們己經可以Web Server作互動了
下面我們要更進一步了解Django Templates的使用方式。故事仍舊要從到我們的MTV架構開始談起。
(資料來源:http://blog.easylearning.guru/implementing-mtv-model-in-python-django/)

在上篇文章中我們的Hello World 網頁使用到了最短路徑,所以使用到了URLS, Views二個元件,其實你也可以使用Python+HTML這種方式土法煉鋼打造你的網站,但是它存在一些問題。
例如可以在view中同時使用Python+HTML去反應使用者的要求。


def current_datetime(request): now = datetime.datetime.now() html = "<html><body>It is now %s.</body></html>" % now return HttpResponse(html)

任何網頁或資料庫設定改變需要改變相對應的python程式碼,我們希望設計改變可以不需要改變Python程式碼。Python and HTML 是二種不同的設計原則,所以為了有效的設計及使用我們使用Tempaltes分開html及python的方式去設計網頁。

 Django Templates 基本概念

Templates依據定義是一個文字字串文件,它的用途是為了分開文件中的資料呈現,在Templates會定義Templates tags去規範文件如何呈現,通常Templates是用來儲存HTML的程式碼。從下面的例子學習如何使用templates 。

 

<html>
<head>
    <title>Ordering notice</title>
</head>
<body>
    <h1>Ordering notice</h1>
    <p>Dear {{ person_name }},</p>
    <p>Thanks for placing an order from {{ company }}. It's scheduled to ship on {{ s\
hip_date|date:"F j, Y" }}.</p>
    <p>Here are the items you've ordered:</p>
    <ul>
        {% for item in item_list %}
        <li>{{ item }}</li>{% endfor %}
    </ul>
    {% if ordered_warranty %}
    <p>Your warranty information will be included in the packaging.</p>
    {% else %}
    <p>
        You didn't order a warranty, so you're on your own when the products inevitably stop working.
    </p>
    {% endif %}
    <p>Sincerely,<br />{{ company }}</p>
</body>
</html>
  •  Templates 大部份儲存HTML程式碼,再加上
  • {{ person_name }} 是一個變數值
  • {% if ordered_warranty %}是 template tag,它比較類似python的程式碼。例如 python的if , for 程式碼
  •  {{ ship_date|date:"F j, Y" }} 是 template filter,它可用來很方更地改變變數的呈現格式。
  • context 是一個 name->value 對應 (類似Python的dictionary),它傳值給 template。
  • template renders 是一個從context取代變數值到指定的模板。
  • 更多template tag 和 template filter 參考https://djangobook.com/basic-template-tags-filters/
  • Advanced 參考https://djangobook.com/advanced-templates/
  • 建議先連結上面二個連結預習一下所有的tag & Filter

 

Templates in Views

如何將Templates整合至Views中,有下面幾種整合方式
(1)Templates 字串匯入

from django.template import Template, Context
from django.http import HttpResponse
import datetime

def current_datetime(request):
    now = datetime.datetime.now()
    t = Template("<html><body>It is now {{ current_date }}.</body></html>")
    html = t.render(Context({'current_date': now}))
    return HttpResponse(html)
  • 第一行匯入Templates 的Context,其內部包含許多定義好的變數及變數值。
  • html 程式碼不長,利用Templates 字串方式

(2)Templates 文件匯入

 

from django.template import Template, Context
from django.http import HttpResponse
import datetime

def current_datetime(request):

    now = datetime.datetime.now()
    # Simple way of using templates from the filesystem.
    # This is BAD because it doesn't account for missing files!
    fp = open('\users\djangouser\templates\mytemplate.html')
    t = Template(fp.read())
    fp.close()

    html = t.render(Context({'current_date': now}))
    return HttpResponse(html)

 

  • 利用open 檔案的方式匯入。
  • 缺點是檔案或路徑不對時會產生錯誤。

(3)指定Templates 文件存放目錄匯入

打開 settings.py 然後在\mysite 建一個 \templates 目錄並加入


TEMPLATE_DIRS = (
    os.path.join(BASE_DIR, 'templates'),
)

 #-------------------------------------------

好了, 現在回到我們的主題view,總共要修改三步驟

(1)用編輯器修改在\mysite_project\settings.py 新增



TEMPLATE_DIRS = (
    os.path.join(BASE_DIR, 'templates'),
)

(2)用編輯器修改在\mysite_project\mysite_app下的view.py

#mysite\mysite\views.py

from django.shortcuts import render
import datetime

def current_datetime(request):
    now = datetime.datetime.now()
    return render(request, 'current_datetime.html', {'current_date': now})

第一個參數為: request 物件
第二個參數:使用的template 檔名 
第三個參數:Context 物件,如空白,則為空Context

(3)在\mysite_project\mysite_app下建一個\templates 子目錄,並且在這個目錄下編寫一個current_datetime.html 檔案

內容如下


<html>
    <body>
        It is now {{ current_date }}
    </body>
</html>

特別注意: 如你的網頁要顯示中文,這個檔案格式要存成UTF8格式。

 

Views 和 Templates 整合測試

在瀏覽器輸入 http://127.0.0.1:8000/time/,你會看到網頁顯示現在時間

  成功了嗎,如不成功再回頭看看那裡有問題,應該不會很困難。

另外利用這個機會改一下語言及時區,修改settings.py 檔案內設定為

LANGUAGE_CODE = 'zh-TW'
TIME_ZONE = 'Asia/Taipei'

回Django Web 程式設計主目錄



 

 

 

 

 

    

 

 

 

 

 

 

 

文章標籤

stanley 發表在 痞客邦 留言(0) 人氣()

2017.08.21 

資料來源: (1)https://www.tutorialspoint.com/django/index.htm
              (2)Writing your first Django app, part 1
              (3)https://djangobook.com/the-django-book/

我們在前面己經安裝好了Portable Python 2.7.6.1後,在這個套件內有一個Django套件,而Django套件可以做什麼呢?

本篇用來記錄Django程式設計過程

什麼是Django ? 簡單地說Django就是用來開發設計Web的程式語言,各位讀者可以想像它就是 Web service架站+ASP(PHP)。
個人認為在專案開發中應用程式可分為GUI程式設計及Web程式設計,兩種應用程式使用類似但不同的設計框架,上層的框架架構或者有些不同,
但在下層的元件使用卻有些類似,但不管如何Django是一種可以用python語言來開發web 應用程式的設計架構。

MTV 架構 ( Model–Template–View )

Django 同樣使用了類似 MVC 的架構,只是在定義和解釋上略為不同,稱為 MTV ( Model–Template–View ),
首先我們要透過下面這張圖來了解其運作方式,這部份對於web程式設計是很重要的
(資料來源:http://blog.easylearning.guru/implementing-mtv-model-in-python-django/)

Model層是存取資料元件,而Template層是資料呈現層次,存放html等語法,view 是企業邏輯層,存放while if等指令。 
最基本地流程如下,

  1. 瀏覽器送出 request(要求)URLS
  2. Django 依據 URL configuration 分配至對應的 View
  3. View 進行操作或其他運算,並回傳一個Response(回應) 物件
  4. 瀏覽器依據 Response(回應) 物件顯示網頁畫面

其他的比較複雜的流程要依應用程式的複製度而加入不同的元件,例如網站需要使用到資料庫時我們就要加入model 層次的元件負責資料庫存取的工作。

檢查你的django和版本 

  
    python -m django --version
  

開始你的第一個Project

開一個cmd視窗,切換到 app/Scripts 所在目錄,在這個目錄下有一個django-admin.py 檔案

執行下面指令

  
    python django-admin.py startproject  <mysite name>
  

執行完後會產生下面的目錄結構

 mysite/
      manage.py
      mysite/
          __init__.py
          settings.py
          urls.py
          wsgi.py
  • manage.py: 一個命令列的公用程式,而這個公用程式可以用不同的方式與Django 專案互動,詳細設定方式在django-admin and manage.py.
  • 內層 mysite/ 目錄是你的專案Python套件,它的名稱為程式中需要匯入的名稱 (e.g. mysite.urls)。
  • 內層mysite/__init__.py: 一個空檔案,而這個檔案告訴Python,更多訊息請參考more about packages
  • 內層mysite/settings.py: Django 專案的設定及配置,如果這個application會被其它projects用到或透過django的database程式架構,
    那要在settings.py當中設定database的相關資訊,透過django的程式架構,如果後端要更換資料庫系統會比較方便,可能改設定就好。
  • 內層mysite/urls.py: Django 專案的URL宣告,負責網站的路由。如果有多個applications,把所有的對應放在一起可能有些混亂,所以django網站上的tutorial建議在建立一個 server_name/app_name/urls.py 檔,然後在 server_name/server_name/urls.py 當中來引用。更多訊息請參考URL dispatcher.
  • 內層mysite/wsgi.py: 一個為WSGI-compatible web servers to serve your project的進入點.更多訊息請參考 How to deploy with WSGI

決定Project Web 應用程式類型

在Django中,一個project即是一個Web應用程式,Project 要依據不同的工作型態而產生不同的目錄結構,而設定方式利用manage.py後的參數來操控不同的應用程式架構。使用方式如下:

  • python manage.py migrate : 建立一個資料庫方案,執行 python manage.py migrate,會根據application的設定來建立資料庫。更多訊息請參考Django settings
  • python manage.py runserver [port]: 開始一個web server
  • python manage.py startapp appname: 為專案建立一個新的app 應用程式
  • python manage.py help : 列出manage.py 所有用的指令

 

(1)建立你的第一個 app

 一個app 是一個 Web應用程式,而web應用程式可做一個投票系統,一個志工系統..等等,而一個專案可以包括數個app
建立app 指令如下:

  python manage.py startapp app_name 

執行完後會產生下面的目錄結構 

app name /
           __init__.py
          admin.py
          models.py

          view.py
          test.py 

 

(2)開啓你的第一個Web Server 

  
    python manage.py runserver
  

c:\python\App\Scripts\prj>python manage.py runserver
Validating models...

0 errors found
August 22, 2017 - 10:13:31
Django version 1.6.2, using settings 'prj.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.

它會在你的本機開一個port 8000的web server,打開你的瀏覽器,輸入網址 http://127.0.0.1:8000/ ,你應該可以看到這個Welcome to Django 的歡迎畫面: 

 

(3)準備遇見你的Hello World View

 

我們開始在瀏覽器上呈現最簡單地訊息顯示,顯示出Hello World,,其中資料流程如下: 

  • 瀏覽器送出 HTTP request
  • Django 依據 URL configuration 分配至對應的 View
  • View 進行資料庫的操作或其他運算,並回傳 HttpResponse 物件
  • 瀏覽器依據 HTTP response 顯示網頁畫面

(3.1)建立Hello World 的 View

請把 view 看成一個 function,輸入 HttpRequest 物件,並回傳 HttpResponse 物件,大致說明如下:

  • 收到 HttpRequest 參數: Django 從網頁接收到 request 後,會將 request 中的資訊封裝產生一個 HttpRequest 物件,並當成第一個參數,傳入對應的 view function。

  • View 處理完後回傳一個 HttpResponse 物件: HttpResponse 物件裡面包含:

    • HttpResponse.content
    • HttpResponse.status_code …等訊息

所以請編輯你的app name / 下的view.py 內容如下:

  # kaok/views.py


from django.http import HttpResponse def hello_world(request): return HttpResponse("Hello World!")

 以上程式就是:

  1.  django.http 模組中引用 HttpResponse 類別
  2. 定義 hello_world 這個 view
  3.  hello_world 被呼叫時,輸入一個HttpRequest 物件,而回傳一個包含字串 Hello World!  HttpResponse 物件。

(3.2)Django URL 設定

 下一步即是要讓Django 知道URL 與 view 的對應關係。例如:當我們在瀏覽 http://127.0.0.1:8000/hello/ 時 ,hello_world() 這個 view function 要能夠被執行。而這個對應關係就被定義在 urls.py。

編輯你的mysite/ 下的urls.py 內容如下:

  # kaok/urls.py

from django.conf.urls import include, url
from django.contrib import admin
from kaok.views import hello_world #Import view functions from kaok.app hello_world
 
urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),
    url(r'^hello/$', hello_world),
]

 

以上程式透過 url() function 傳入兩個參數 regex, view

  url(regex, view)

 

  • regex -- 定義的 URL 規則
    • 規則以 regular expression(正規表示式)來表達
    • r'^hello/$' 代表的是 hello/ 這種 URL
  • view -- 對應的 view function
    • 指的是 hello_world 這個 view

    在這個URL 設定中必須使用到Regular Expressions,如果你没學過它,可能會不知道這是什麼東西,我個人建議花點時間去研究及熟悉它,它的功能很強很方便
學了它我保證你絕對不會後悔,很多地方或程式都有它的影子,如果現在不懂那就先複製-貼上吧!有興趣可看官方文件及找估狗大師了。

(3)測試 你的Hello World

在瀏覽器輸入 http://127.0.0.1:8000/hello/,你會看到網頁顯示我們在 HttpResponse 傳入的文字Hello World!。

 如能走到這個地步,表示你的一些基本環境己經可以工作了,下面我們將更進一步設計比較複雜的網站內容。

回Django Web 程式設計主目錄

 

文章標籤

stanley 發表在 痞客邦 留言(0) 人氣()

 

如何利用python 的Socket 來撰寫通程式

官方文件https://docs.python.org/2/howto/sockets.html
好站連接:(Server端)  http://www.binarytides.com/python-socket-programming-tutorial/


Server code

# -*- coding: big5 -*-

import socket                                       
from time import ctime

# create a socket object
serversocket = socket.socket(
         socket.AF_INET, socket.SOCK_STREAM)

# get local machine name
host = socket.gethostname()                          

port = 9999                                          

# bind to the port
serversocket.bind((host, port))                                 

# queue up to 5 requests
serversocket.listen(5)  

while True:
  print 'waiting for connection...'
  tcpTimeClientSock, addr = serversocket.accept()
  print '...connected from:', addr

  while True:
    data = tcpTimeClientSock.recv(1024)
    if not data:  break
    print data
    reply = 'OK...' + data
    tcpTimeClientSock.send('[%s] %s' % (ctime(), reply))
   
   
  tcpTimeClientSock.close()
serversocket.close()

#----------------------

Client code

# -*- coding: big5 -*-

import socket
import sys

colors = ['red', 'green']

host = socket.gethostname()   
port = 9999                   # The same port as used by the server
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((host, port))

while True:
  indata = raw_input('> ')
  if not indata:
      break
  sock.send(indata)
  data = sock.recv(1024)
  if not data:
      break
  print data
sock.close()

 

 

 

 

 

文章標籤

stanley 發表在 痞客邦 留言(0) 人氣()

 2017.07.28 星期五

測量車子速度看起來應該簡單,但還是要實作才能發覺真正的問題,其實看別人做好像很簡單,但實際上也是很多程式碼要寫,要做到完善似乎也是不容易的。所以記錄下來,以作參考。
這個範例使用web server 去呈現轉速資料,要修改成自己能用的。

 

 

There are 2 methods for calculating speed using Python.

The first method is using "pre-defined interval".
The second method is using "calculated interval".

#---------------------------------------

CALCULATED INTERVAL METHOD


Using calculated interval method is better and more precise than pre-defined interval.
 (1)using the time.time() module in Python to precisely measure time duration of each interrupt interval.
(2)using add_event_detect() to take advantage of the GPIO pin interrupt event handler.
(3)useing one callback function called "calculate_elapse(channel)".
     This function will get called anytime interrupt event happens.

#-------公式----------------------------------
Round Per Minute (rpm) can be calculated using : rpm = 1/elapse * 60
where 1 is referring to 1 complete rotation and 60 is referring to 60 seconds.

circ_cm (wheel circumference) can be calculated using : 2 x pi x radius

dist_km (distance moved in km) can be calculated using : dist_km = circ_cm/100000

km_per_sec (speed in KM/s) calculated using: km_per_sec =  dist_km / elapse

km_per_hour (speed in KM/h) calculated using: km_per_hour =  km_per_sec * 3600

#-------------------------------

#!/usr/bin/python3
import RPi.GPIO as GPIO
from time import sleep
import time, math

dist_meas = 0.00
km_per_hour = 0
rpm = 0
elapse = 0
sensor = 12
pulse = 0
start_timer = time.time()

def init_GPIO(): # initialize GPIO
     GPIO.setmode(GPIO.BCM)
     GPIO.setwarnings(False)
     GPIO.setup(sensor,GPIO.IN,GPIO.PUD_UP)

def calculate_elapse(channel):              # callback function
      global pulse, start_timer, elapse
      pulse+=1                                           # increase pulse by 1 whenever interrupt occurred
      elapse = time.time() - start_timer        # elapse for every 1 complete rotation made!
      start_timer = time.time()                    # let current time equals to start_timer

def calculate_speed(r_cm):
     global pulse,elapse,rpm,dist_km,dist_meas,km_per_sec,km_per_hour
     if elapse !=0:                                        # to avoid DivisionByZero error
        rpm = 1/elapse * 60
        circ_cm = (2*math.pi)*r_cm               # calculate wheel circumference in CM
        dist_km = circ_cm/100000                  # convert cm to km
        km_per_sec = dist_km / elapse           # calculate KM/sec
        km_per_hour = km_per_sec * 3600    # calculate KM/h
        dist_meas = (dist_km*pulse)*1000     # measure distance traverse in meter
return km_per_hour

def init_interrupt():
     GPIO.add_event_detect(sensor, GPIO.FALLING, callback = calculate_elapse, bouncetime = 20)

if __name__ == '__main__':
init_GPIO()
init_interrupt()
while True:
calculate_speed(20)                          # call this function with wheel radius as parameter
  print('rpm:{0:.0f}-RPM kmh:{1:.0f}-KMH dist_meas:{2:.2f}m pulse:{3}'.format(rpm,km_per_hour,dist_meas,pulse))
sleep(0.1)

 

 

參考資料

Raspberry Pi based Speedometer using Hall Effect Sensor

Speed sensor calculation using Python

https://stackoverflow.com/questions/40738776/how-to-use-python-to-measure-speed-of-bike-like-a-digital-speedometer-using-a-r

 

文章標籤

stanley 發表在 痞客邦 留言(0) 人氣()

 

2017 06 03

當使用 ftp.nlst 去列出在Server上的檔案,但是當程式在Server上找不到任何符合條件的檔案時
程式會中止且產生下面的錯誤訊息

ftplib.error_perm: 550 No files found.

 

我們可使用下面的程式片段去解決這個空目錄的問題

try:
    ls = ftp.nlst('D1*.txt')
except ftplib.error_perm as e:
    print "Directory is empty : "+str(e)
    exit(1)

 

回主目錄

文章標籤

stanley 發表在 痞客邦 留言(0) 人氣()

2017/05/25

此需求是以python和openpyxl,ftplib為主,從unix主機下載指定的csv檔,並且自動的將csv轉成xlsx檔案
而其中第一row為中文標題,而第三column為日期yy/mm/dd形式,我們要將日期格式轉成yy/mm/dd的文字格式

#-------------------------------------------
# -*- coding: big5 -*-
from ftplib import FTP, all_errors
from openpyxl import Workbook
from openpyxl.styles import Font, Fill
import datetime
import wx
import os
import re
import csv
import sys

def getFile(filename):
    try:
       ftp.retrbinary("RETR " + filename ,open(filename, 'wb').write)
    except:
       print('檔案下載失敗!')
       print "Error"
 
try:
       ftp = FTP("XXX.XXX.XX.XX")
       ftp.login("XX","XXX")
       print('使用者連線成功')
    
except AttributeError:
       print('連線失敗(主機或帳號或密碼錯誤)')
       ftp = None
      
except all_errors, err:
       print(str(err))
       ftp = None

# download the file 
local_Dir  = "c:\\tmp"
host_Dir = r"/BACK2/f/"
print "Changing local directory to " + local_Dir
os.chdir(local_Dir)
print 'Changing remote directory to ' + host_Dir
ftp.cwd(host_Dir)
ls = ftp.nlst('*-*.csv')
count = len(ls)
curr = 0 
print "found {} files".format(count)
for filename in ls:
    curr += 1   
    print "get file {} to {}".format(filename,local_Dir)
    getFile(filename)                                                  #從unix 的指定目錄下下載指定的檔案  
 
ftp.quit()
ftp = None
print('ftp離線')                                                   # ftp 完作成且離線
#-------- open csv and transfer to excel automatically--------
for fnList in ls:                                                          #依次開啓所有的csv檔案
  fileName, file_extension = os.path.splitext(fnList)
  saveFn = fileName + '.xlsx'                                     #分開檔名及檔案 extension
  print saveFn                                                           #印出每個檔案l值,視情況可以省略
  wb = Workbook()
  ws = wb.active           
  with open(fnList, 'r') as f:
     reader = csv.reader(f)
     for r, row in enumerate(reader):                            #設定row 迴圈
       for c, col in enumerate(row):                               #設定column 迴圈
         for idx, val in enumerate(col.split(',')):
           cell = ws.cell(row=r+1, column=c+1)
           cell.font = Font(size=12)                                 #設定字體大小
           if (c == 3 and r > 0):                                      #特殊需求處理,要將日期格式轉成文字格式
             val = "{:10}".format(val)                              #特殊需求處,只有第3column及row2以後要處理格式
             cell.value = val                                             #將值填入cell內  
             cell.number_format = 'yy/mm/dd'                  #文字格式
           else:
             cell.value = val.decode('big5')
                        
           print cell.value                                       #印出每個cell值,視情況可以省略

  wb.save(saveFn)

文章標籤

stanley 發表在 痞客邦 留言(0) 人氣()

             下載影片的方法巿很多種,,而個人比較推薦的是利用Python 語言所開發的youtube-dl, 這是一個在命令列操作的軟體, 使用方法很簡單,只要輸入youtube-dl  URL 即可下載檔案,而需要圖形介面的使用者可下載Youtube-dlG,它是利用wxPython開發可跨平臺的 youtube-dlG (youtube-dl-gui) 當做 youtube-dl 的前端圖形操作界面

如讀者的系統為Windows 則直接下載執行檔即可使用,而Liunx 使用者要準備好Python,WxPython軟體安裝,要按照安裝程序準備安執行環境。

youtube-dl有很多參數可以使用,底下列出HELP的參數:

Usage: youtube-dl-script.py [OPTIONS] URL [URL...]
 
Options:
  General Options:
    -h, --help                       Print this help text and exit
    --version                        Print program version and exit
    -U, --update                     Update this program to latest version. Make sure that you have sufficient permissions (run with sudo if needed)
    -i, --ignore-errors              Continue on download errors, for example to skip unavailable videos in a playlist
    --abort-on-error                 Abort downloading of further videos (in the playlist or the command line) if an error occurs
    --dump-user-agent                Display the current browser identification
    --list-extractors                List all supported extractors
    --extractor-descriptions         Output descriptions of all supported  extractors
    --force-generic-extractor        Force extraction to use the generic extractor
    --default-search PREFIX          Use this prefix for unqualified URLs. For
                                     example "gvsearch2:" downloads two videos
                                     from google videos for youtube-dl "large
                                     apple". Use the value "auto" to let
                                     youtube-dl guess ("auto_warning" to emit a
                                     warning when guessing). "error" just throws
                                     an error. The default value "fixup_error"
                                     repairs broken URLs, but emits an error if
                                     this is not possible instead of searching.
    --ignore-config                  Do not read configuration files. When given
                                     in the global configuration file /etc
                                     /youtube-dl.conf: Do not read the user
                                     configuration in ~/.config/youtube-
                                     dl/config (%APPDATA%/youtube-dl/config.txt
                                     on Windows)
    --config-location PATH           Location of the configuration file; either the path to the config or its containing  directory.
    --flat-playlist                  Do not extract the videos of a playlist, only list them.
    --mark-watched                   Mark videos watched (YouTube only)
    --no-mark-watched                Do not mark videos watched (YouTube only)
    --no-color                       Do not emit color codes in output
 
  Network Options:
    --proxy URL                      Use the specified HTTP/HTTPS/SOCKS proxy.
                                     To enable experimental SOCKS proxy, specify
                                     a proper scheme. For example
                                     socks5://127.0.0.1:1080/. Pass in an empty
                                     string (--proxy "") for direct connection
    --socket-timeout SECONDS         Time to wait before giving up, in seconds
    --source-address IP              Client-side IP address to bind to
    -4, --force-ipv4                 Make all connections via IPv4
    -6, --force-ipv6                 Make all connections via IPv6
 
  Geo Restriction:
    --geo-verification-proxy URL     Use this proxy to verify the IP address for
                                     some geo-restricted sites. The default
                                     proxy specified by --proxy (or none, if the
                                     options is not present) is used for the actual downloading.
    --geo-bypass                     Bypass geographic restriction via faking X-Forwarded-For HTTP header (experimental)
    --no-geo-bypass                  Do not bypass geographic restriction via
                                     faking X-Forwarded-For HTTP header (experimental)
    --geo-bypass-country CODE        Force bypass geographic restriction with
                                     explicitly provided two-letter ISO 3166-2 country code (experimental)
 
  Video Selection:
    --playlist-start NUMBER          Playlist video to start at (default is 1)
    --playlist-end NUMBER            Playlist video to end at (default is last)
    --playlist-items ITEM_SPEC       Playlist video items to download. Specify
                                     indices of the videos in the playlist
                                     separated by commas like: "--playlist-items
                                     1,2,5,8" if you want to download videos
                                     indexed 1, 2, 5, 8 in the playlist. You can
                                     specify range: "--playlist-items
                                     1-3,7,10-13", it will download the videos
                                     at index 1, 2, 3, 7, 10, 11, 12 and 13.
    --match-title REGEX              Download only matching titles (regex or caseless sub-string)
    --reject-title REGEX             Skip download for matching titles (regex or caseless sub-string)
    --max-downloads NUMBER           Abort after downloading NUMBER files
   --min-filesize SIZE              Do not download any videos smaller than  SIZE (e.g. 50k or 44.6m)
    --max-filesize SIZE              Do not download any videos larger than SIZE (e.g. 50k or 44.6m)
    --date DATE                      Download only videos uploaded in this date
    --datebefore DATE                Download only videos uploaded on or before  this date (i.e. inclusive)
    --dateafter DATE                 Download only videos uploaded on or after this date (i.e. inclusive)
    --min-views COUNT                Do not download any videos with less than  COUNT views
    --max-views COUNT                Do not download any videos with more than COUNT views
    --match-filter FILTER            Generic video filter. Specify any key (see
                                     help for -o for a list of available keys)
                                     to match if the key is present, !key to
                                     check if the key is not present, key >
                                     NUMBER (like "comment_count > 12", also
                                     works with >=, <, <=, !=, =) to compare
                                     against a number, key = 'LITERAL' (like
                                     "uploader = 'Mike Smith'", also works with
                                     !=) to match against a string literal and &
                                     to require multiple matches. Values which
                                     are not known are excluded unless you put a
                                     question mark (?) after the operator. For
                                     example, to only match videos that have
                                     been liked more than 100 times and disliked
                                     less than 50 times (or the dislike
                                     functionality is not available at the given
                                     service), but who also have a description,
                                     use --match-filter "like_count > 100 &
                                     dislike_count <? 50 & description" .
    --no-playlist                    Download only the video, if the URL refers  to a video and a playlist.
    --yes-playlist                   Download the playlist, if the URL refers to a video and a playlist.
    --age-limit YEARS                Download only videos suitable for the given age
    --download-archive FILE          Download only videos not listed in the
                                     archive file. Record the IDs of all downloaded videos in it.
    --include-ads                    Download advertisements as well (experimental)
 
  Download Options:
    -r, --limit-rate RATE            Maximum download rate in bytes per second  (e.g. 50K or 4.2M)
    -R, --retries RETRIES            Number of retries (default is 10), or "infinite".
    --fragment-retries RETRIES       Number of retries for a fragment (default is 10), or "infinite" (DASH, hlsnative and ISM)
    --skip-unavailable-fragments     Skip unavailable fragments (DASH, hlsnative  and ISM)
    --abort-on-unavailable-fragment  Abort downloading when some fragment is not available
    --keep-fragments                 Keep downloaded fragments on disk after downloading is finished; fragments are erased by default
    --buffer-size SIZE               Size of download buffer (e.g. 1024 or 16K) (default is 1024)
    --no-resize-buffer               Do not automatically adjust the buffer
                                     size. By default, the buffer size is automatically resized from an initial value  of SIZE.
    --playlist-reverse               Download playlist videos in reverse order
    --playlist-random                Download playlist videos in random order
    --xattr-set-filesize             Set file xattribute ytdl.filesize with  expected file size (experimental)
    --hls-prefer-native              Use the native HLS downloader instead of ffmpeg
    --hls-prefer-ffmpeg              Use ffmpeg instead of the native HLS downloader
    --hls-use-mpegts                 Use the mpegts container for HLS videos,
                                     allowing to play the video while
                                     downloading (some players may not be able to play it)
    --external-downloader COMMAND    Use the specified external downloader.
                                     Currently supports aria2c,avconv,axel,curl,ffmpeg,httpie,wget
    --external-downloader-args ARGS  Give these arguments to the external downloader
 
  Filesystem Options:
    -a, --batch-file FILE            File containing URLs to download ('-' for
                                     stdin)
    --id                             Use only video ID in file name
    -o, --output TEMPLATE            Output filename template, see the "OUTPUT
                                     TEMPLATE" for all the info
    --autonumber-start NUMBER        Specify the start value for %(autonumber)s
                                     (default is 1)
    --restrict-filenames             Restrict filenames to only ASCII
                                     characters, and avoid "&" and spaces in
                                     filenames
    -w, --no-overwrites              Do not overwrite files
    -c, --continue                   Force resume of partially downloaded files.
                                     By default, youtube-dl will resume
                                     downloads if possible.
    --no-continue                    Do not resume partially downloaded files
                                     (restart from beginning)
    --no-part                        Do not use .part files - write directly
                                     into output file
    --no-mtime                       Do not use the Last-modified header to set
                                     the file modification time
    --write-description              Write video description to a .description
                                     file
    --write-info-json                Write video metadata to a .info.json file
    --write-annotations              Write video annotations to a
                                     .annotations.xml file
    --load-info-json FILE            JSON file containing the video information
                                     (created with the "--write-info-json"
                                     option)
    --cookies FILE                   File to read cookies from and dump cookie
                                     jar in
    --cache-dir DIR                  Location in the filesystem where youtube-dl
                                     can store some downloaded information
                                     permanently. By default $XDG_CACHE_HOME
                                     /youtube-dl or ~/.cache/youtube-dl . At the
                                     moment, only YouTube player files (for  videos with obfuscated signatures) are cached, but that may change.
    --no-cache-dir                   Disable filesystem caching
    --rm-cache-dir                   Delete all filesystem cache files
 
  Thumbnail images:
    --write-thumbnail                Write thumbnail image to disk
    --write-all-thumbnails           Write all thumbnail image formats to disk
    --list-thumbnails                Simulate and list all available thumbnail formats
 
  Verbosity / Simulation Options:
    -q, --quiet                      Activate quiet mode
    --no-warnings                    Ignore warnings
    -s, --simulate                   Do not download the video and do not write  anything to disk
    --skip-download                  Do not download the video
    -g, --get-url                    Simulate, quiet but print URL
    -e, --get-title                  Simulate, quiet but print title
    --get-id                         Simulate, quiet but print id
    --get-thumbnail                  Simulate, quiet but print thumbnail URL
    --get-description                Simulate, quiet but print video description
    --get-duration                   Simulate, quiet but print video length
    --get-filename                   Simulate, quiet but print output filename
    --get-format                     Simulate, quiet but print output format
    -j, --dump-json                  Simulate, quiet but print JSON information.
                                     See --output for a description of available
                                     keys.
    -J, --dump-single-json           Simulate, quiet but print JSON information
                                     for each command-line argument. If the URL
                                     refers to a playlist, dump the whole
                                     playlist information in a single line.
    --print-json                     Be quiet and print the video information as
                                     JSON (video is still being downloaded).
    --newline                        Output progress bar as new lines
    --no-progress                    Do not print progress bar
    --console-title                  Display progress in console titlebar
    -v, --verbose                    Print various debugging information
    --dump-pages                     Print downloaded pages encoded using base64
                                     to debug problems (very verbose)
    --write-pages                    Write downloaded intermediary pages to
                                     files in the current directory to debug problems
    --print-traffic                  Display sent and read HTTP traffic
    -C, --call-home                  Contact the youtube-dl server for debugging
    --no-call-home                   Do NOT contact the youtube-dl server for debugging
 
  Workarounds:
    --encoding ENCODING              Force the specified encoding (experimental)
    --no-check-certificate           Suppress HTTPS certificate validation
    --prefer-insecure                Use an unencrypted connection to retrieve information about the video. (Currently supported only for YouTube)
    --user-agent UA                  Specify a custom user agent
    --referer URL                    Specify a custom referer, use if the video access is restricted to one domain
    --add-header FIELD:VALUE         Specify a custom HTTP header and its value, separated by a colon ':'. You can use this option multiple times
    --bidi-workaround                Work around terminals that lack bidirectional text support. Requires bidiv or fribidi executable in PATH
    --sleep-interval SECONDS         Number of seconds to sleep before each
                                     download when used alone or a lower bound
                                     of a range for randomized sleep before each
                                     download (minimum possible number of
                                     seconds to sleep) when used along with--max-sleep-interval.
    --max-sleep-interval SECONDS     Upper bound of a range for randomized sleep
                                     before each download (maximum possible
                                     number of seconds to sleep). Must only be
                                     used along with --min-sleep-interval.
 
  Video Format Options:
    -f, --format FORMAT              Video format code, see the "FORMAT SELECTION" for all the info
    --all-formats                    Download all available video formats
    --prefer-free-formats            Prefer free video formats unless a specific one is requested
    -F, --list-formats               List all available formats of requested videos
    --youtube-skip-dash-manifest     Do not download the DASH manifests and  related data on YouTube videos
    --merge-output-format FORMAT     If a merge is required (e.g.
                                     bestvideo+bestaudio), output to given
                                     container format. One of mkv, mp4, ogg,
                                     webm, flv. Ignored if no merge is required
 
  Subtitle Options:
    --write-sub                      Write subtitle file
    --write-auto-sub                 Write automatically generated subtitle file (YouTube only)
    --all-subs                       Download all the available subtitles of the video
    --list-subs                      List all available subtitles for the video
    --sub-format FORMAT              Subtitle format, accepts formats
                                     preference, for example: "srt" or "ass/srt/best"
    --sub-lang LANGS                 Languages of the subtitles to download
                                     (optional) separated by commas, use --list-subs for available language tags
 
  Authentication Options:
    -u, --username USERNAME          Login with this account ID
    -p, --password PASSWORD          Account password. If this option is left out, youtube-dl will ask interactively.
    -2, --twofactor TWOFACTOR        Two-factor authentication code
    -n, --netrc                      Use .netrc authentication data
    --video-password PASSWORD        Video password (vimeo, smotri, youku)
 
  Adobe Pass Options:
    --ap-mso MSO                     Adobe Pass multiple-system operator (TV
                                     provider) identifier, use --ap-list-mso for a list of available MSOs
    --ap-username USERNAME           Multiple-system operator account login
    --ap-password PASSWORD           Multiple-system operator account password.
                                     If this option is left out, youtube-dl will ask interactively.
    --ap-list-mso                    List all supported multiple-system operators
 
  Post-processing Options:
    -x, --extract-audio              Convert video files to audio-only files
                                     (requires ffmpeg or avconv and ffprobe or
                                     avprobe)
    --audio-format FORMAT            Specify audio format: "best", "aac",
                                     "flac", "mp3", "m4a", "opus", "vorbis", or
                                     "wav"; "best" by default; No effect without -x
    --audio-quality QUALITY          Specify ffmpeg/avconv audio quality, insert
                                     a value between 0 (better) and 9 (worse)
                                     for VBR or a specific bitrate like 128K (default 5)
    --recode-video FORMAT            Encode the video to another format if necessary (currently supported:
                                                         mp4|flv|ogg|webm|mkv|avi)
    --postprocessor-args ARGS        Give these arguments to the postprocessor
    -k, --keep-video                          Keep the video file on disk after the post-processing; the video is erased by default
    --no-post-overwrites             Do not overwrite post-processed files; the  post-processed files are overwritten by default
    --embed-subs                     Embed subtitles in the video (only for mp4,webm and mkv videos)
    --embed-thumbnail                Embed thumbnail in the audio as cover art
    --add-metadata                   Write metadata to the video file
    --metadata-from-title FORMAT     Parse additional metadata like song title /
                                     artist from the video title. The format
                                     syntax is the same as --output, the parsed
                                     parameters replace existing values.
                                     Additional templates: %(album)s,
                                     %(artist)s. Example: --metadata-from-title
                                     "%(artist)s - %(title)s" matches a title
                                     like "Coldplay - Paradise"
    --xattrs                         Write metadata to the video file's xattrs
                                     (using dublin core and xdg standards)
    --fixup POLICY                   Automatically correct known faults of the
                                               file. One of never (do nothing), warn (only emit a warning), detect_or_warn
                                                (the default; fix file if we can, warn otherwise)
    --prefer-avconv                  Prefer avconv over ffmpeg for running the postprocessors (default)
    --prefer-ffmpeg                  Prefer ffmpeg over avconv for running the postprocessors
    --ffmpeg-location PATH           Location of the ffmpeg/avconv binary;
                                     either the path to the binary or its containing directory.
    --exec CMD              Execute a command on the file after downloading, similar to find's -exec
                                     syntax. Example: --exec 'adb push {}  /sdcard/Music/ && rm {}'
    --convert-subs FORMAT            Convert the subtitles to other format (currently supported: srt|ass|vtt)
#-------------------------------------------------

註:據說 Youtube 連結網址如果有「&」的話會導致下載失敗,可以前後用雙引號包起來就可以解決這個問題

 

官方網址及下載點(youtube-dl持續更新版本,請下載最新版本,目前為2017.05.01)

安裝步驟

在windows 下,如下載youtube-dl-2017.05.01.exe,則直接執行即可,
如為youtube-dl-2017.05.01.zip, 則要解開ZIP檔案後,找到setup.py, 然後執行 
python setup.py install 

最後執行完畢後會在 E:\XX\APP\Scripts 下新增 youtube-dl.exe 

 

文章標籤

stanley 發表在 痞客邦 留言(0) 人氣()

 

Creating a Class

 

#An example of a class
class Shape:

    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.description = "This shape has not been described yet"
        self.author = "Nobody has claimed to make this shape yet"

    def area(self):
        return self.x * self.y

    def perimeter(self):
        return 2 * self.x + 2 * self.y

    def describe(self, text):
        self.description = text

    def authorName(self, text):
        self.author = text

    def scaleSize(self, scale):
        self.x = self.x * scale
        self.y = self.y * scale

Using a Class

rectangle = Shape(100, 45)

 

accessing attributes from outside an instance

#finding the area of your rectangle:
print(rectangle.area())

#finding the perimeter of your rectangle:
print(rectangle.perimeter())

#describing the rectangle
rectangle.describe("A wide rectangle, more than twice\
 as wide as it is tall")

#making the rectangle 50% smaller
rectangle.scaleSize(0.5)

#re-printing the new area of the rectangle
print(rectangle.area())

Built-In Class Attributes

  • __dict__: Dictionary containing the class's namespace.

  • __doc__: Class documentation string or none, if undefined.

  • __name__: Class name.

  • __module__: Module name in which the class is defined. This attribute is "__main__" in interactive mode.

  • __bases__: A possibly empty tuple containing the base classes, in the order of their occurrence in the base class list.

  • 更多特殊class attributes 說明請參考here

#!/usr/bin/python

class Employee:
   'Common base class for all employees'
   empCount = 0

   def __init__(self, name, salary):
      self.name = name
      self.salary = salary
      Employee.empCount += 1
   
   def displayCount(self):
     print "Total Employee %d" % Employee.empCount

   def displayEmployee(self):
      print "Name : ", self.name,  ", Salary: ", self.salary

print "Employee.__doc__:", Employee.__doc__
print "Employee.__name__:", Employee.__name__
print "Employee.__module__:", Employee.__module__
print "Employee.__bases__:", Employee.__bases__
print "Employee.__dict__:", Employee.__dict__
Employee.__doc__: Common base class for all employees
Employee.__name__: Employee
Employee.__module__: __main__
Employee.__bases__: ()
Employee.__dict__: {'__module__': '__main__', 'displayCount':
<function displayCount at 0xb7c84994>, 'empCount': 2, 
'displayEmployee': <function displayEmployee at 0xb7c8441c>, 
'__doc__': 'Common base class for all employees', 
'__init__': <function __init__ at 0xb7c846bc>}

Destroying Objects (Garbage Collection)

#!/usr/bin/python

class Point:
   def __init( self, x=0, y=0):
      self.x = x
      self.y = y
   def __del__(self):
      class_name = self.__class__.__name__
      print class_name, "destroyed"

pt1 = Point()
pt2 = pt1
pt3 = pt1
print id(pt1), id(pt2), id(pt3) # prints the ids of the obejcts
del pt1
del pt2
del pt3

Inheritance

class Square(Shape):
    def __init__(self,x):
        self.x = x
        self.y = x

 

#!/usr/bin/python

class Parent:        # define parent class
   parentAttr = 100
   def __init__(self):
      print "Calling parent constructor"

   def parentMethod(self):
      print 'Calling parent method'

   def setAttr(self, attr):
      Parent.parentAttr = attr

   def getAttr(self):
      print "Parent attribute :", Parent.parentAttr

class Child(Parent): # define child class
   def __init__(self):
      print "Calling child constructor"

   def childMethod(self):
      print 'Calling child method'

c = Child()          # instance of child
c.childMethod()      # child calls its method
c.parentMethod()     # calls parent's method
c.setAttr(200)       # again call parent's method
c.getAttr()          # again call parent's method

When the above code is executed, it produces the following result −

Calling child constructor
Calling child method
Calling parent method
Parent attribute : 200

Overriding Methods

#!/usr/bin/python

class Parent:        # define parent class
   def myMethod(self):
      print 'Calling parent method'

class Child(Parent): # define child class
   def myMethod(self):
      print 'Calling child method'

c = Child()          # instance of child
c.myMethod()         # child calls overridden method

Base Overloading Methods

SN Method, Description & Sample Call
1 __init__ ( self [,args...] )
Constructor (with any optional arguments)
Sample Call : obj = className(args)
2 __del__( self )
Destructor, deletes an object
Sample Call : del obj
3 __repr__( self )
Evaluatable string representation
Sample Call : repr(obj)
4 __str__( self )
Printable string representation
Sample Call : str(obj)
5 __cmp__ ( self, x )
Object comparison
Sample Call : cmp(obj, x)

Overloading Operators

You could, however, define the __add__ method in your class to perform vector addition and then the plus operator would behave as per expectation

#!/usr/bin/python

class Vector:
   def __init__(self, a, b):
      self.a = a
      self.b = b

   def __str__(self):
      return 'Vector (%d, %d)' % (self.a, self.b)
   
   def __add__(self,other):
      return Vector(self.a + other.a, self.b + other.b)

v1 = Vector(2,10)
v2 = Vector(5,-2)
print v1 + v2

Data Hiding

An object's attributes may or may not be visible outside the class definition. You need to name attributes with a double underscore prefix, and those attributes then are not be directly visible to outsiders.

#!/usr/bin/python

class JustCounter:
   __secretCount = 0
  
   def count(self):
      self.__secretCount += 1
      print self.__secretCount

counter = JustCounter()
counter.count()
counter.count()
print counter.__secretCount

When the above code is executed, it produces the following result −

Traceback (most recent call last):
  File "test.py", line 12, in <module>
    print counter.__secretCount
AttributeError: JustCounter instance has no attribute '__secretCount'

 

參考資料: https://www.tutorialspoint.com/python/python_classes_objects.htm

 

回主目錄

 

文章標籤

stanley 發表在 痞客邦 留言(0) 人氣()

了解 super() 、self 和 *args and **kwargs 用法

在 python 物件方法中,如果存取一個 class 或者 instance 中的變數, 那麼在物件方法宣告參數時,就必須要有一個 self 當作第一個參數。
self就是代表該 instance 自身
#-------------------------

內建函數 (function) super() ,用為呼叫父類別定義的方法

super([type [,object-or-type]]) Return a **proxy object** that delegates method calls to a **parent or sibling** class of type.

class MyParentClass():
def __init__(self, x, y):
pass

class SubClass(MyParentClass):
def __init__(self, x, y):super().__init__(x, y)  # 呼叫父類別__init__()

我們需要在子類別初始化父類別,python 的super 函數簡化設計 

原文網址:https://kknews.cc/zh-tw/other/29r9qy.html

#----------------------------------

*args and **kwargs 用法

Example 1 :

#  傳入字串資料
def print_args(d1, d2, d3):
    print(d1, d2, d3)

data = ('foo', 'bar', 'baz')
print_args(*data)
>>> foo bar baz

# 傳入數值資料
def print_args(*args):
    for arg in args:
        print(arg)
print_args(1, 2, 3)
>>> 1
>>> 2
>>> 3

def print_args(*args):
    print(args)
print_args(1, 2, 3)
>>> (1, 2, 3)

# 傳出數值資料
def print_args(a, b, c, *args):
    print(a, b, c, args)
print_args(1, 2, 3, 4, 5)
>>> 1 2 3 (4, 5)


def print_kwargs(**kwargs):
    print(kwargs)
print_kwargs(foo='bar', hello='world')
>>> {'foo': 'bar', 'hello': 'world'}

def print_kwargs(latitude=None, longitude=None):
    print(latitude, longitude)

data = {'latitude': 0.00, 'longitude': 1.00}
print_data(**data)
>>> 0.00 1.00

def print_kwargs(lat=None, long=None, **kwargs):
    print(lat, long, kwargs)
print_kwargs(1, 2, data='other')
>>> 1 2 {'data': 'other'}

# 包含在繼承內

class Base(object):
    def __init__(self, *args, data=None, **kwargs):
        print('data is: ', data)

class MyBaseObject(Base):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

class MyObject(MyBaseObject):
    def __init__(self, *args, game=None, **kwargs):
        super().__init__(*args, **kwargs)
        print('game is: ', game)

my_data = {'game': 'UT', 'data': '3d'}
MyObject(**my_data)
>>> data is: 3d
>>> game is: UT

 

example 2 :

class A(object):
 
    def __init__(self, *args, **kwargs):
        super(A, self).__init__(*args, **kwargs)
        self.number = kwargs['number']
 
    def helloA(self):
        return self.number
 
class B(object):
 
    def __init__(self, *args, **kwargs):
        super(B, self).__init__()
        self.message = kwargs['message']
 
    def helloB(self):
        return self.message
 
class C(A,B):
 
    def __init__(self, *args, **kwargs):
        # Notice: only one call to super... due to mro
        super(C, self).__init__(*args, **kwargs)
 
    def helloC(self):
        print "Calling A: ", self.helloA()
        print "Calling B: ", self.helloB()  
 
def main():
    c = C(number=42, message="Joe")
    c.helloC()
 
if __name__ == '__main__':
    main()

 

$ python mrotest.py 
Calling A:  42
Calling B:  Joe

回主目錄

 

 

文章標籤

stanley 發表在 痞客邦 留言(0) 人氣()

 

一次搞懂BoxSizer

没有這些額外的參數設定,則所有的元件會依原本的大小放置在box的左上角內,而所有元件的大小不會依視窗大小的變化不會伸展或縮減。
如下圖所示,有些元件高度有高有低不會變大小。所以我們必須適當的設定
proportions, flags, and borders 參數

box = wx.BoxSizer(integer orient)
box.Add(wx.Window window, integer proportion=0, integer flag = 0, integer border = 0)

下面是一個基本的簡單例子

class BoxSizerPanel(wx.Panel):
def __init__(self, parent, *args, **kwargs):
        super(BoxSizerPanel, self).__init__(*args, **kwargs)

        # Attributes
        self._field1 = wx.TextCtrl(self)
        self._field2 = wx.TextCtrl(self)

        # Layout
        self._DoLayout()

def _DoLayout(self):
    vsizer = wx.BoxSizer(wx.VERTICAL)
    field1_sz = wx.BoxSizer(wx.HORIZONTAL)
    field2_sz = wx.BoxSizer(wx.HORIZONTAL)
    # 增加 兩個 labels
    field1_lbl = wx.StaticText(self, label="Field 1:")
    field2_lbl = wx.StaticText(self, label="Field 2:")

    # label and field 加至第一個水平box
   field1_sz.AddSpacer(50) #增加50 px 空白
    field1_sz.Add(field1_lbl) #加入label 1
    field1_sz.AddSpacer(5) #增加 5px 空白
    field1_sz.Add(self._field1) #加入field 1
    field1_sz.AddSpacer(50)  
   # label and field 加至第二個水平box
    field2_sz.AddSpacer(50)
    field2_sz.Add(field2_lbl)
    field2_sz.AddSpacer(5)
    field2_sz.Add(self._field2)
    field2_sz.AddSpacer(50)
    # 增加二個水平box 至一個較大的直box
    vsizer.AddSpacer(50)
    vsizer.Add(field1_sz)
    vsizer.AddSpacer(15)
    vsizer.Add(field2_sz)
    vsizer.AddSpacer(50)
    # 指定主要外層box 至panel
    self.SetSizer(vsizer)

 

sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(wx.Button(self, -1, 'An extremely long button text'), 0, 0, 0)
sizer.Add(wx.Button(self, -1, 'Small button'), 0, 0, 0)
self.SetSizer(sizer)

_images/boxsizer1.png

 sizer = wx.BoxSizer(wx.VERTICAL)
 sizer.Add(wx.Button(self, -1, 'An extremely long button text'), 0, 0, 0)
 sizer.Add(wx.Button(self, -1, 'Small button'), 0, 0, 0)
 sizer.SetSizeHints(self)
 self.SetSizer(sizer)

_images/boxsizer2.png

The proportion parameter

sizer = wx.BoxSizer(wx.VERTICAL)
# Second button is three times as tall as first button
sizer.Add(wx.Button(self, -1, 'An extremely long button text'), 1, 0, 0)
sizer.Add(wx.Button(self, -1, 'Small button'), 3, 0, 0)
sizer.SetSizeHints(self)
self.SetSizer(sizer)

_images/boxsizer3.png

sizer = wx.BoxSizer(wx.VERTICAL)
# First button is 3/2 the height of the second button
sizer.Add(wx.Button(self, -1, 'An extremely long button text'), 3, 0, 0)
sizer.Add(wx.Button(self, -1, 'Small button'), 2, 0, 0)
sizer.SetSizeHints(self)
self.SetSizer(sizer)

_images/boxsizer32.png

If one of the proportion parameters is 0, that wx.Window will be the minimum size, and the others will resize proportionally:

sizer = wx.BoxSizer(wx.VERTICAL)
# Third button is twice the size of the second button
sizer.Add(wx.Button(self, -1, 'An extremely long button text'), 0, 0, 0)
sizer.Add(wx.Button(self, -1, 'Small button'), 1, 0, 0)
sizer.Add(wx.Button(self, -1, 'Another button'), 2, 0, 0)
sizer.SetSizeHints(self)
self.SetSizer(sizer)

_images/boxsizer33.png

The flags and border parameters

Sizer Flag Description
wx.TOP
wx.BOTTOM
wx.LEFT
wx.RIGHT
wx.ALL
These flags are used to specify which side(s) of the sizer item the border width will apply to.
wx.EXPAND The item will be expanded to fill the space assigned to the item.
wx.SHAPED The item will be expanded as much as possible while also maintaining its aspect ratio
wx.FIXED_MINSIZE Normally wx.Sizers will use wx.Window.GetEffectiveMinSize to determine what the minimal size of window items should be, and will use that size to calculate the layout. This allows layouts to adjust when an item changes and its best size becomes different. If you would rather have a window item stay the size it started with then use wx.FIXED_MINSIZE.
wx.RESERVE_SPACE_EVEN_IF_HIDDEN Normally wx.Sizers don’t allocate space for hidden windows or other items. This flag overrides this behavior so that sufficient space is allocated for the window even if it isn’t visible. This makes it possible to dynamically show and hide controls without resizing parent dialog, for example.
wx.ALIGN_CENTER or wx.ALIGN_CENTRE
wx.ALIGN_LEFT
wx.ALIGN_RIGHT
wx.ALIGN_RIGHT
wx.ALIGN_TOP
wx.ALIGN_BOTTOM
wx.ALIGN_CENTER_VERTICAL or wx.ALIGN_CENTRE_VERTICAL
wx.ALIGN_CENTER_HORIZONTAL or wx.ALIGN_CENTRE_HORIZONTAL
The wx.ALIGN* flags allow you to specify the alignment of the item within the space allotted to it by the sizer, adjusted for the border if any.
sizer = wx.BoxSizer(wx.VERTICAL)
# Second button is right aligned
sizer.Add(wx.Button(self, -1, "An extremely long button text"), 0, 0, 0)
sizer.Add(wx.Button(self, -1, "Small Button"), 0, wx.ALIGN_RIGHT, 0)
sizer.SetSizeHints(self)
self.SetSizer(sizer)

_images/boxsizer4.png

sizer = wx.BoxSizer(wx.VERTICAL)
# Second button is center-aligned
sizer.Add(wx.Button(self, -1, "An extremely long button text"), 0, 0, 0)
sizer.Add(wx.Button(self, -1, "Small Button"), 0, wx.ALIGN_CENTER, 0)
sizer.SetSizeHints(self)
self.SetSizer(sizer)

_images/boxsizer41.png

sizer = wx.BoxSizer(wx.VERTICAL)
# Second button expands to the whole parent's width
sizer.Add(wx.Button(self, -1, "An extremely long button text"), 0, 0, 0)
sizer.Add(wx.Button(self, -1, "Small Button"), 0, wx.EXPAND, 0)
sizer.SetSizeHints(self)
self.SetSizer(sizer)

_images/boxsizer5.png

sizer = wx.BoxSizer(wx.VERTICAL)
# Second button will scale proportionally
sizer.Add(wx.Button(self, -1, "An extremely long button text"), 0, 0, 0)
sizer.Add(wx.Button(self, -1, "Small Button"), 1, wx.SHAPED, 0)
sizer.SetSizeHints(self)
self.SetSizer(sizer)

_images/boxsizer51.png

sizer = wx.BoxSizer(wx.VERTICAL)
# Border size effects
sizer.Add(wx.Button(self, -1, "An extremely long button text"), 0, 0, 0)
sizer.Add(wx.Button(self, -1, "Small Button"), 0, wx.EXPAND | wx.LEFT, 20)
sizer.SetSizeHints(self)
self.SetSizer(sizer)

_images/boxsizer53.png

sizer = wx.BoxSizer(wx.VERTICAL)
# Border size effects
sizer.Add(wx.Button(self, -1, "An extremely long button text"), 0, 0, 0)
sizer.Add(wx.Button(self, -1, "Small Button"), 0, wx.EXPAND | wx.LEFT | wx.RIGHT, 20)
sizer.SetSizeHints(self)
self.SetSizer(sizer)

_images/boxsizer54.png

sizer = wx.BoxSizer(wx.VERTICAL)
# Border size effects
sizer.Add(wx.Button(self, -1, "An extremely long button text"), 0, 0, 0)
sizer.Add(wx.Button(self, -1, "Small Button"), 0, wx.EXPAND | wx.LEFT | wx.RIGHT | wx.TOP, 20)
sizer.SetSizeHints(self)
self.SetSizer(sizer)

_images/boxsizer55.png

sizer = wx.BoxSizer(wx.VERTICAL)
# Border size effects
sizer.Add(wx.Button(self, -1, "An extremely long button text"), 0, 0, 0)
sizer.Add(wx.Button(self, -1, "Small Button"), 0, wx.EXPAND | wx.ALL, 20)
sizer.SetSizeHints(self)
self.SetSizer(sizer)

_images/boxsizer56.png

BoxSizer

_images/overview_sizer_08.png

StaticBoxSizer

_images/overview_sizer_09.png

GridSizer

_images/overview_sizer_10.png

FlexGridSizer

_images/overview_sizer_11.png

 

 

 


參考資料:

https://www.packtpub.com/books/content/wxpython-28-window-layout-and-design
https://wxpython.org/Phoenix/docs/html/sizers_overview.html

回主目錄

 

文章標籤

stanley 發表在 痞客邦 留言(0) 人氣()

 

#-------Echo Server Python Code ------------

import socket
srvsock = socket.socket( socket.AF_INET, socket.SOCK_STREAM )
srvsock.bind( ('', 23000) )
srvsock.listen( 5 )
while 1:
 print("Echo Server Start ..... wait client")
 clisock, (remhost, remport) = srvsock.accept()
 print("Client address is " + remhost + ":" + str(remport))
 str = clisock.recv(100)
 clisock.send( str )
 clisock.close()

#-------Client Python Code ------------

import socket
clisock = socket.socket( socket.AF_INET, socket.SOCK_STREAM )
clisock.connect( ('your IP Address', 23000) )
clisock.send("Hello World\n")
print clisock.recv(100)
clisock.close()

#-----------------------------
Building a simple (non-rendering) HTTP client with httplib

import httplib
httpconn = httplib.HTTPConnection("www.ibm.com")
httpconn.request("GET", "/developerworks/index.html")
resp = httpconn.getresponse()
if resp.reason == "OK":
     resp_data = resp.read()
     print resp_data
httpconn.close()

#------------------------
Sending a short e-mail message with smtplib
import smtplib
fromAdrs = 'mtj@mtjones.com'
toAdrs = 'you@mail.com'
msg = 'From: me@mail.com\r\n
To: you@mail.com\r\nSubject:Hello\r\nHi!\r\n'
mailClient = smtplib.SMTP('192.168.1.1')
mailClient.sendmail( fromAdrs, toAdrs, msg )
mailClient.quit
#------------------

# Retrieving e-mail messages from a POP3 mail server and emitting the subject line

import poplib
import re
popClient = poplib.POP3('192.168.1.1')
popClient.user('user')
popClient.pass_('password')
numMsgs, mboxSize = popClient.stat()
print "Number of messages ", numMsgs
print "Mailbox size", mboxSize

for id in range (numMsgs):
 for mail in popClient.retr(id+1)[1]:
   if re.search( 'Subject:', mail ):
     print mail


popClient.quit()

 

回主目錄

文章標籤

stanley 發表在 痞客邦 留言(0) 人氣()

使用wxPython 模組視窗程式設計-簡單ftp client 程式
讀者可以這個為基礎,變化成較複雜的ftp client 程式,例如加入
wx.Gauge元件以傳輸較大的檔案。

# -*- coding: big5 -*-
from ftplib import FTP, all_errors
import wx
import os

class MyStatusBar(wx.StatusBar):

    def __init__(self, parent):
        super(MyStatusBar, self).__init__(parent)

        self.SetFieldsCount(2)
        self.SetStatusText('Welcome to ftp client', 0)
        self.SetStatusWidths([-1, 120])

        self.Bind(wx.EVT_SIZE, self.OnSize)

    def OnSize(self, e):
        e.Skip()

class MyFtp(wx.Frame):

    def __init__(self, *args, **kw):
        super(MyFtp, self).__init__(*args, **kw)

        self.InitUI()

    def InitUI(self):

        wx.StaticText(self, label='Ftp site', pos=(10, 20))             #設定 label 資料
        wx.StaticText(self, label='Login', pos=(10, 60))
        wx.StaticText(self, label='Password', pos=(10, 100))
        wx.StaticText(self, label='本機檔案', pos=(10, 140))
        wx.StaticText(self, label='遠端目錄', pos=(10, 180))

        self.ftpsite = wx.TextCtrl(self, pos=(100, 15),size=(160, -1))      #設定輸入 TXT 資料
        self.login = wx.TextCtrl(self,  pos=(100, 55),size=(160, -1))
        self.password = wx.TextCtrl(self, pos=(100, 95),size=(160, -1), style=wx.TE_PASSWORD)
        self.local =  wx.TextCtrl(self,  pos=(100, 135),size=(160, -1))
        self.remote = wx.TextCtrl(self,  pos=(100, 175),size=(160, -1))

        self.ftpsite.SetValue("XX.XX.XX.XX")                                           #設定預設值
        self.login.SetValue("XXXXX")
        self.password.SetValue("XXX")
        self.local.SetValue("c:/tmp/XXX.txt")
        self.remote.SetValue("/XXX/XXX/")

        self.ftp = None

        con = wx.Button(self, label='連線', pos=(10, 250))                       #設定連線按鈕
        discon = wx.Button(self, label='斷線', pos=(120, 250))
        transfer = wx.Button(self, label='上傳資料', pos=(230, 250))

        self.Bind(wx.EVT_BUTTON, self.OnConnect, con)                         #設定連線bind
        self.Bind(wx.EVT_BUTTON, self.OnDisConnect, discon)
        transfer.Bind(wx.EVT_BUTTON, self.ToggleTrans)

        self.sb = MyStatusBar(self)
        self.SetStatusBar(self.sb)

        self.SetSize((350,380))
        self.SetTitle('FTP Client')
        self.Centre()
        self.Show()

    def OnConnect(self, e):                                                                      #連線事件動作
        if not self.ftp:

            ftpsite = self.ftpsite.GetValue()
            login = self.login.GetValue()
            password = self.password.GetValue()
            self.localFile =  self.local.GetValue()
            self.remote = self.remote.GetValue()

            try:
                self.ftp = FTP(ftpsite)
                var = self.ftp.login(login, password)
                self.sb.SetStatusText('使用者連線成功')

            except AttributeError:

                self.sb.SetStatusText('連線失敗(主機或帳號或密碼錯誤)')
                self.ftp = None

            except all_errors, err:

                self.sb.SetStatusText(str(err))
                self.ftp = None

    def OnDisConnect(self, e):        #離線事件動作

        if self.ftp:

            self.ftp.quit()
            self.ftp = None

            self.sb.SetStatusText('使用者已離線')

    def ToggleTrans(self, e):         #檔案上傳事件動作
        self.ftp.cwd(self.remote)
        upFile = self.localFile
        baseName = os.path.basename(upFile)
        dirName = os.path.dirname(upFile)
        os.chdir(dirName)
        upFile = baseName
        print(dirName+'/'+upFile)
        # ----- asc mode -----------
        file = open(upFile, "r")
        self.ftp.storlines("STOR " + upFile , file)
        #------ binary mode ---------
        #fh = open(upFile, 'rb')
        #self.ftp.storbinary('STOR ' + "id.txt" , fh)
        #--------------------
        print("檔案上傳成功!")
        self.sb.SetStatusText('檔案上傳成功!')
        wx.MessageBox('檔案上傳成功!', '上傳結果通知',wx.OK | wx.ICON_INFORMATION)
        self.Destroy()

#---主程式----------------

def main():

    ex = wx.App()
    MyFtp(None)
    ex.MainLoop()

if __name__ == '__main__':
    main()

回主目錄

文章標籤

stanley 發表在 痞客邦 留言(0) 人氣()

(1) 使用Pyodbc 連接syabse資料庫

import pyodbc
print ("Begin Syabse ODBC connect.....")

dsn="DSN=mysybase_db"
cnnctn=pyodbc.connect(dsn)
print("Successfully established connection....")
cnnctn.autocommit = True
cur = cnnctn.cursor()
cur.execute("select book_no,year,author from booksell where year = 2016")
while True:
   row = cur.fetchone()
   if (not row):
       break
   print("%s:%s" % (row[0],row[1]))
cur.close()
cnnctn.close()
input("press any key ccontinue...")

(2) 使用Podbc 連接access資料庫

import pyodbc

print ("Begin ACCESS ODBC connect.....")

DBfile = 'booksell.mdb'
conn = pyodbc.connect('DRIVER={Microsoft Access Driver (*.mdb)};DBQ='+DBfile)
print("Successfully established connection....")

#use below conn if using with Access 2007, 2010 .accdb file
#conn = pyodbc.connect(r'Driver={Microsoft Access Driver (*.mdb, *.accdb)};DBQ='+DBfile)
cursor = conn.cursor()

SQL = 'select book_no,year,author from booksell where year = 2016;'
for row in cursor.execute(SQL):                  # cursors are iterable
    print row.book_no,row.year,row.author

 # print row
# if print row it will return tuple of all fields

cursor.close()
conn.close()

回主目錄

 

 

stanley 發表在 痞客邦 留言(0) 人氣()

使用wxPython 模組視窗程式設計-第四篇

目前使用的環境:windows 7、Portable Python 2.7.6.1、wxPython 3.0
這章將加入更多元件例子,我只寫程式碼,複製程式碼執行可以看到測試結果,如此方便學習及加速開發程式時間,但
更多說明要自己參考下面的參考文件。

Application skeletons in wxPython

File Manager

File manager

SpreadSheet

Spreadsheet

Player

Player

Browser

Browser

Creating custom widgets

A hyperlink widget

Link widget

Burning widget

Burning widget on Linux

The CPU widget

CPU widget

Kika(ftp client)

Kika

Tom (sends an email)

Tom

參考資料:http://zetcode.com/wxpython/

回主目錄

stanley 發表在 痞客邦 留言(0) 人氣()

使用wxPython 模組去記錄視窗程式設計-第三篇

目前使用的環境:windows 7、Portable Python 2.7.6.1、wxPython 3.0
這章將加入更多元件例子,我只寫程式碼,複製程式碼執行可以看到測試結果,如此方便學習及加速開發程式時間,但
更多說明要自己參考下面的參考文件。

wxWindow Hierarchy

wxButton Hierarchy

wxPython dialogs
(1) A Simple message box
import wx

class Example(wx.Frame):

    def __init__(self, *args, **kwargs):
        super(Example, self).__init__(*args, **kwargs)

        self.InitUI()

    def InitUI(self):

        wx.FutureCall(5000, self.ShowMessage)

        self.SetSize((300, 200))
        self.SetTitle('Message box')
        self.Centre()
        self.Show(True)

    def ShowMessage(self):
        wx.MessageBox('Download completed', 'Info',wx.OK | wx.ICON_INFORMATION)

def main():

    ex = wx.App()
    Example(None)
    ex.MainLoop()

if __name__ == '__main__':
    main()

Message box

(2)message flag 

flag meaning
wx.OK show OK button
wx.CANCEL show Cancel button
wx.YES_NO show Yes, No buttons
wx.YES_DEFAULT make Yes button the default
wx.NO_DEFAULT make No button the default
wx.ICON_EXCLAMATION show an alert icon
wx.ICON_ERROR show an error icon
wx.ICON_HAND same as wx.ICON_ERROR
wx.ICON_INFORMATION show an info icon
wx.ICON_QUESTION show a question icon

Widgets

wx.Button
 

import wx

class Example(wx.Frame):

    def __init__(self, *args, **kw):
        super(Example, self).__init__(*args, **kw)

        self.InitUI()

    def InitUI(self):

        pnl = wx.Panel(self)
        cbtn = wx.Button(pnl, label='Close', pos=(20, 30))

        cbtn.Bind(wx.EVT_BUTTON, self.OnClose)

        self.SetSize((250, 200))
        self.SetTitle('wx.Button')
        self.Centre()
        self.Show(True)

    def OnClose(self, e):

        self.Close(True)

def main():

    ex = wx.App()
    Example(None)
    ex.MainLoop()


if __name__ == '__main__':
    main()

wx.Button

wx.ToggleButton

wx.ToggleButton is a button that has two states: pressed and not pressed

import wx


class Example(wx.Frame):

    def __init__(self, *args, **kw):
        super(Example, self).__init__(*args, **kw)

        self.InitUI()

    def InitUI(self):

        pnl = wx.Panel(self)

        self.col = wx.Colour(0, 0, 0)

        rtb = wx.ToggleButton(pnl, label='red', pos=(20, 25))
        gtb = wx.ToggleButton(pnl, label='green', pos=(20, 60))
        btb = wx.ToggleButton(pnl, label='blue', pos=(20, 100))

        self.cpnl  = wx.Panel(pnl, pos=(150, 20), size=(110, 110))
        self.cpnl.SetBackgroundColour(self.col)

        rtb.Bind(wx.EVT_TOGGLEBUTTON, self.ToggleRed)
        gtb.Bind(wx.EVT_TOGGLEBUTTON, self.ToggleGreen)
        btb.Bind(wx.EVT_TOGGLEBUTTON, self.ToggleBlue)

        self.SetSize((300, 200))
        self.SetTitle('Toggle buttons')
        self.Centre()
        self.Show(True)

    def ToggleRed(self, e):

        obj = e.GetEventObject()
        isPressed = obj.GetValue()

        green = self.col.Green()
        blue = self.col.Blue()

        if isPressed:
            self.col.Set(255, green, blue)
        else:
            self.col.Set(0, green, blue)

        self.cpnl.SetBackgroundColour(self.col)
        self.cpnl.Refresh()

    def ToggleGreen(self, e):

        obj = e.GetEventObject()
        isPressed = obj.GetValue()

        red = self.col.Red()
        blue = self.col.Blue()

        if isPressed:
            self.col.Set(red, 255, blue)
        else:
            self.col.Set(red, 0, blue)

        self.cpnl.SetBackgroundColour(self.col)
        self.cpnl.Refresh()

    def ToggleBlue(self, e):

        obj = e.GetEventObject()
        isPressed = obj.GetValue()

        red = self.col.Red()
        green = self.col.Green()

        if isPressed:
            self.col.Set(red, green, 255)
        else:
            self.col.Set(red, green, 0)

        self.cpnl.SetBackgroundColour(self.col)
        self.cpnl.Refresh()


def main():

    ex = wx.App()
    Example(None)
    ex.MainLoop()


if __name__ == '__main__':
    main()

Toggle buttons

wx.StaticLine

import wx


class Example(wx.Frame):

    def __init__(self, *args, **kw):
        super(Example, self).__init__(*args, **kw)

        self.InitUI()

    def InitUI(self):

        pnl = wx.Panel(self)

        font = wx.Font(10, wx.DEFAULT, wx.NORMAL, wx.BOLD)
        heading = wx.StaticText(self, label='The Central Europe', pos=(130, 15))
        heading.SetFont(font)

        wx.StaticLine(self, pos=(25, 50), size=(300,1))

        wx.StaticText(self, label='Slovakia', pos=(25, 80))
        wx.StaticText(self, label='Hungary', pos=(25, 100))
        wx.StaticText(self, label='Poland', pos=(25, 120))
        wx.StaticText(self, label='Czech Republic', pos=(25, 140))
        wx.StaticText(self, label='Germany', pos=(25, 160))
        wx.StaticText(self, label='Slovenia', pos=(25, 180))
        wx.StaticText(self, label='Austria', pos=(25, 200))
        wx.StaticText(self, label='Switzerland', pos=(25, 220))

        wx.StaticText(self, label='5 445 000', pos=(250, 80))
        wx.StaticText(self, label='10 014 000', pos=(250, 100))
        wx.StaticText(self, label='38 186 000', pos=(250, 120))
        wx.StaticText(self, label='10 562 000', pos=(250, 140))
        wx.StaticText(self, label='81 799 000', pos=(250, 160))
        wx.StaticText(self, label='2 050 000', pos=(250, 180))
        wx.StaticText(self, label='8 414 000', pos=(250, 200))
        wx.StaticText(self, label='7 866 000', pos=(250, 220))

        wx.StaticLine(self, pos=(25, 260), size=(300,1))

        tsum = wx.StaticText(self, label='164 336 000', pos=(240, 280))
        sum_font = tsum.GetFont()
        sum_font.SetWeight(wx.BOLD)
        tsum.SetFont(sum_font)

        btn = wx.Button(self, label='Close', pos=(140, 310))

        btn.Bind(wx.EVT_BUTTON, self.OnClose)

        self.SetSize((360, 380))
        self.SetTitle('wx.StaticLine')
        self.Centre()
        self.Show(True)

    def OnClose(self, e):

        self.Close(True)

def main():

    ex = wx.App()
    Example(None)
    ex.MainLoop()

if __name__ == '__main__':
    main()

wx.StaticLine

wx.StaticText
A wx.StaticText widget displays one or more lines of read-only text.

import wx


class Example(wx.Frame):

    def __init__(self, *args, **kw):
        super(Example, self).__init__(*args, **kw)

        self.InitUI()

    def InitUI(self):

        txt1 = '''I'm giving up the ghost of love
in the shadows cast on devotion
She is the one that I adore
creed of my silent suffocation
Break this bittersweet spell on me
lost in the arms of destiny'''

        txt2 = '''There is something in the way
You're always somewhere else
Feelings have deserted me
To a point of no return
I don't believe in God
But I pray for you'''

        pnl = wx.Panel(self)
        vbox = wx.BoxSizer(wx.VERTICAL)

        st1 = wx.StaticText(pnl, label=txt1, style=wx.ALIGN_CENTRE)
        st2 = wx.StaticText(pnl, label=txt2, style=wx.ALIGN_CENTRE)

        vbox.Add(st1, flag=wx.ALL, border=5)
        vbox.Add(st2, flag=wx.ALL, border=5)
        pnl.SetSizer(vbox)

        self.SetSize((250, 260))
        self.SetTitle('Bittersweet')
        self.Centre()
        self.Show(True)

def main():

    ex = wx.App()
    Example(None)
    ex.MainLoop()

if __name__ == '__main__':
    main()

wx.StaticText

wxPython - TextCtrl 

import wx

class Mywin(wx.Frame):
   def __init__(self, parent, title):
      super(Mywin, self).__init__(parent, title = title,size = (350,250))

      panel = wx.Panel(self)
      vbox = wx.BoxSizer(wx.VERTICAL)

      hbox1 = wx.BoxSizer(wx.HORIZONTAL)
      l1 = wx.StaticText(panel, -1, "Text Field")

      hbox1.Add(l1, 1, wx.EXPAND|wx.ALIGN_LEFT|wx.ALL,5)
      self.t1 = wx.TextCtrl(panel)                           #wx.TextCtrl 元件 t1

      hbox1.Add(self.t1,1,wx.EXPAND|wx.ALIGN_LEFT|wx.ALL,5)
      self.t1.Bind(wx.EVT_TEXT,self.OnKeyTyped)      #wx.TextCtrl 元件 t1 bind
      vbox.Add(hbox1)

      hbox2 = wx.BoxSizer(wx.HORIZONTAL)
      l2 = wx.StaticText(panel, -1, "password field")

      hbox2.Add(l2, 1, wx.ALIGN_LEFT|wx.ALL,5)
      self.t2 = wx.TextCtrl(panel,style = wx.TE_PASSWORD)   #wx.TextCtrl 元件 t2
      self.t2.SetMaxLength(5)

      hbox2.Add(self.t2,1,wx.EXPAND|wx.ALIGN_LEFT|wx.ALL,5)
      vbox.Add(hbox2)
      self.t2.Bind(wx.EVT_TEXT_MAXLEN,self.OnMaxLen)  #wx.TextCtrl 元件 t2 bind

      hbox3 = wx.BoxSizer(wx.HORIZONTAL)
      l3 = wx.StaticText(panel, -1, "Multiline Text")

      hbox3.Add(l3,1, wx.EXPAND|wx.ALIGN_LEFT|wx.ALL,5)
      self.t3 = wx.TextCtrl(panel,size = (200,100),style = wx.TE_MULTILINE)  #wx.TextCtrl 元件 t3

      hbox3.Add(self.t3,1,wx.EXPAND|wx.ALIGN_LEFT|wx.ALL,5)
      vbox.Add(hbox3)
      self.t3.Bind(wx.EVT_TEXT_ENTER,self.OnEnterPressed)    #wx.TextCtrl 元件 t3 bind

      hbox4 = wx.BoxSizer(wx.HORIZONTAL)
      l4 = wx.StaticText(panel, -1, "Read only text")

      hbox4.Add(l4, 1, wx.EXPAND|wx.ALIGN_LEFT|wx.ALL,5)
      self.t4 = wx.TextCtrl(panel, value = "ReadOnlyText",style = wx.TE_READONLY|wx.TE_CENTER) #wx.TextCtrl 元件 t4

      hbox4.Add(self.t4,1,wx.EXPAND|wx.ALIGN_LEFT|wx.ALL,5)
      vbox.Add(hbox4)
      panel.SetSizer(vbox)

      self.Centre()
      self.Show()
      self.Fit()

   def OnKeyTyped(self, event):
      print event.GetString()

   def OnEnterPressed(self,event):
      print "Enter pressed"

   def OnMaxLen(self,event):
      print "Maximum length reached"

app = wx.App()
Mywin(None,  'TextCtrl demo')
app.MainLoop()

TextCtrl Output

wx.StaticBox

import wx


class Example(wx.Frame):

    def __init__(self, *args, **kw):
        super(Example, self).__init__(*args, **kw)

        self.InitUI()

    def InitUI(self):

        pnl = wx.Panel(self)

        wx.StaticBox(pnl, label='Personal Info', pos=(5, 5), size=(240, 170))
        wx.CheckBox(pnl, label='Male', pos=(15, 30))
        wx.CheckBox(pnl, label='Married', pos=(15, 55))
        wx.StaticText(pnl, label='Age', pos=(15, 95))
        wx.SpinCtrl(pnl, value='1', pos=(55, 90), size=(60, -1), min=1, max=120)

        btn = wx.Button(pnl, label='Ok', pos=(90, 185), size=(60, -1))

        btn.Bind(wx.EVT_BUTTON, self.OnClose)

        self.SetSize((270, 250))
        self.SetTitle('Static box')
        self.Centre()
        self.Show(True)

    def OnClose(self, e):

        self.Close(True)


def main():

    ex = wx.App()
    Example(None)
    ex.MainLoop()


if __name__ == '__main__':
    main()

Static box

wx.ComboBox

import wx


class Example(wx.Frame):

    def __init__(self, *args, **kw):
        super(Example, self).__init__(*args, **kw)

        self.InitUI()

    def InitUI(self):

        pnl = wx.Panel(self)

        distros = ['Ubuntu', 'Arch', 'Fedora', 'Debian', 'Mint']
        cb = wx.ComboBox(pnl, pos=(50, 30), choices=distros,
            style=wx.CB_READONLY)

        self.st = wx.StaticText(pnl, label='', pos=(50, 140))
        cb.Bind(wx.EVT_COMBOBOX, self.OnSelect)

        self.SetSize((250, 230))
        self.SetTitle('wx.ComboBox')
        self.Centre()
        self.Show(True)

    def OnSelect(self, e):

        i = e.GetString()
        self.st.SetLabel(i)

def main():

    ex = wx.App()
    Example(None)
    ex.MainLoop()

if __name__ == '__main__':
    main()

wx.ComboBox

wx.CheckBox

import wx


class Example(wx.Frame):

    def __init__(self, *args, **kw):
        super(Example, self).__init__(*args, **kw)

        self.InitUI()

    def InitUI(self):

        pnl = wx.Panel(self)

        cb = wx.CheckBox(pnl, label='Show title', pos=(20, 20))
        cb.SetValue(True)

        cb.Bind(wx.EVT_CHECKBOX, self.ShowOrHideTitle)

        self.SetSize((250, 170))
        self.SetTitle('wx.CheckBox')
        self.Centre()
        self.Show(True)

    def ShowOrHideTitle(self, e):

        sender = e.GetEventObject()
        isChecked = sender.GetValue()

        if isChecked:
            self.SetTitle('wx.CheckBox')
        else:
            self.SetTitle('')

def main():

    ex = wx.App()
    Example(None)
    ex.MainLoop()

if __name__ == '__main__':
    main()

wx.CheckBox

wx.StatusBar

import wx

class Example(wx.Frame):

    def __init__(self, *args, **kw):
        super(Example, self).__init__(*args, **kw)

        self.InitUI()

    def InitUI(self):

        pnl = wx.Panel(self)

        button = wx.Button(pnl, label='Button', pos=(20, 20))
        text = wx.CheckBox(pnl, label='CheckBox', pos=(20, 90))
        combo = wx.ComboBox(pnl, pos=(120, 22), choices=['Python', 'Ruby'])
        slider = wx.Slider(pnl, 5, 6, 1, 10, (120, 90), (110, -1))

        pnl.Bind(wx.EVT_ENTER_WINDOW, self.OnWidgetEnter)
        button.Bind(wx.EVT_ENTER_WINDOW, self.OnWidgetEnter)
        text.Bind(wx.EVT_ENTER_WINDOW, self.OnWidgetEnter)
        combo.Bind(wx.EVT_ENTER_WINDOW, self.OnWidgetEnter)
        slider.Bind(wx.EVT_ENTER_WINDOW, self.OnWidgetEnter)

        self.sb = self.CreateStatusBar()

        self.SetSize((250, 230))
        self.SetTitle('wx.Statusbar')
        self.Centre()
        self.Show(True)

    def OnWidgetEnter(self, e):

        name = e.GetEventObject().GetClassName()
        self.sb.SetStatusText(name + ' widget')
        e.Skip()

def main():

    ex = wx.App()
    Example(None)
    ex.MainLoop()

if __name__ == '__main__':
    main()

StatusBar

wx.RadioButton

import wx


class Example(wx.Frame):

    def __init__(self, *args, **kw):
        super(Example, self).__init__(*args, **kw)

        self.InitUI()

    def InitUI(self):

        pnl = wx.Panel(self)

        self.rb1 = wx.RadioButton(pnl, label='Value A', pos=(10, 10),
            style=wx.RB_GROUP)
        self.rb2 = wx.RadioButton(pnl, label='Value B', pos=(10, 30))
        self.rb3 = wx.RadioButton(pnl, label='Value C', pos=(10, 50))

        self.rb1.Bind(wx.EVT_RADIOBUTTON, self.SetVal)
        self.rb2.Bind(wx.EVT_RADIOBUTTON, self.SetVal)
        self.rb3.Bind(wx.EVT_RADIOBUTTON, self.SetVal)

        self.sb = self.CreateStatusBar(3)

        self.sb.SetStatusText("True", 0)
        self.sb.SetStatusText("False", 1)
        self.sb.SetStatusText("False", 2)

        self.SetSize((210, 210))
        self.SetTitle('wx.RadioButton')
        self.Centre()
        self.Show(True)

    def SetVal(self, e):

        state1 = str(self.rb1.GetValue())
        state2 = str(self.rb2.GetValue())
        state3 = str(self.rb3.GetValue())

        self.sb.SetStatusText(state1, 0)
        self.sb.SetStatusText(state2, 1)
        self.sb.SetStatusText(state3, 2)

def main():

    ex = wx.App()
    Example(None)
    ex.MainLoop()

if __name__ == '__main__':
    main()

wx.RadioButton

wx.Gauge

import wx

TASK_RANGE = 50

class Example(wx.Frame):

    def __init__(self, *args, **kw):
        super(Example, self).__init__(*args, **kw)

        self.InitUI()

    def InitUI(self):

        self.timer = wx.Timer(self, 1)
        self.count = 0

        self.Bind(wx.EVT_TIMER, self.OnTimer, self.timer)

        pnl = wx.Panel(self)
        vbox = wx.BoxSizer(wx.VERTICAL)
        hbox1 = wx.BoxSizer(wx.HORIZONTAL)
        hbox2 = wx.BoxSizer(wx.HORIZONTAL)
        hbox3 = wx.BoxSizer(wx.HORIZONTAL)

        self.gauge = wx.Gauge(pnl, range=TASK_RANGE, size=(250, 25))
        self.btn1 = wx.Button(pnl, wx.ID_OK)
        self.btn2 = wx.Button(pnl, wx.ID_STOP)
        self.text = wx.StaticText(pnl, label='Task to be done')

        self.Bind(wx.EVT_BUTTON, self.OnOk, self.btn1)
        self.Bind(wx.EVT_BUTTON, self.OnStop, self.btn2)

        hbox1.Add(self.gauge, proportion=1, flag=wx.ALIGN_CENTRE)
        hbox2.Add(self.btn1, proportion=1, flag=wx.RIGHT, border=10)
        hbox2.Add(self.btn2, proportion=1)
        hbox3.Add(self.text, proportion=1)
        vbox.Add((0, 30))
        vbox.Add(hbox1, flag=wx.ALIGN_CENTRE)
        vbox.Add((0, 20))
        vbox.Add(hbox2, proportion=1, flag=wx.ALIGN_CENTRE)
        vbox.Add(hbox3, proportion=1, flag=wx.ALIGN_CENTRE)

        pnl.SetSizer(vbox)

        self.SetSize((300, 200))
        self.SetTitle('wx.Gauge')
        self.Centre()
        self.Show(True)

    def OnOk(self, e):

        if self.count >= TASK_RANGE:
            return

        self.timer.Start(100)
        self.text.SetLabel('Task in Progress')

    def OnStop(self, e):

        if self.count == 0 or self.count >= TASK_RANGE or not self.timer.IsRunning():
            return

        self.timer.Stop()
        self.text.SetLabel('Task Interrupted')

    def OnTimer(self, e):

        self.count = self.count + 1
        self.gauge.SetValue(self.count)

        if self.count == TASK_RANGE:

            self.timer.Stop()
            self.text.SetLabel('Task Completed')

def main():

    ex = wx.App()
    Example(None)
    ex.MainLoop()

if __name__ == '__main__':
    main()

wx.Gauge

wx.Slider

import wx


class Example(wx.Frame):

    def __init__(self, *args, **kw):
        super(Example, self).__init__(*args, **kw)

        self.InitUI()

    def InitUI(self):

        pnl = wx.Panel(self)

        sld = wx.Slider(pnl, value=200, minValue=150, maxValue=500, pos=(20, 20),
            size=(250, -1), style=wx.SL_HORIZONTAL)

        sld.Bind(wx.EVT_SCROLL, self.OnSliderScroll)

        self.txt = wx.StaticText(pnl, label='200', pos=(20, 90))

        self.SetSize((290, 200))
        self.SetTitle('wx.Slider')
        self.Centre()
        self.Show(True)

    def OnSliderScroll(self, e):

        obj = e.GetEventObject()
        val = obj.GetValue()

        self.txt.SetLabel(str(val))


def main():

    ex = wx.App()
    Example(None)
    ex.MainLoop()

if __name__ == '__main__':
    main()

wx.Slider

wx.SpinCtrl

import wx


class Example(wx.Frame):

    def __init__(self, *args, **kw):
        super(Example, self).__init__(*args, **kw)

        self.InitUI()

    def InitUI(self):

        pnl = wx.Panel(self)


        wx.StaticText(self, label='Convert Fahrenheit temperature to Celsius',
            pos=(20,20))
        wx.StaticText(self, label='Fahrenheit: ', pos=(20, 80))
        wx.StaticText(self, label='Celsius: ', pos=(20, 150))

        self.celsius = wx.StaticText(self, label='', pos=(150, 150))
        self.sc = wx.SpinCtrl(self, value='0', pos=(150, 75), size=(60, -1))
        self.sc.SetRange(-459, 1000)

        btn = wx.Button(self, label='Compute', pos=(70, 230))
        btn.SetFocus()
        cbtn = wx.Button(self, label='Close', pos=(185, 230))

        btn.Bind(wx.EVT_BUTTON, self.OnCompute)
        cbtn.Bind(wx.EVT_BUTTON, self.OnClose)

        self.SetSize((350, 310))
        self.SetTitle('wx.SpinCtrl')
        self.Centre()
        self.Show(True)

    def OnClose(self, e):

        self.Close(True)

    def OnCompute(self, e):

        fahr = self.sc.GetValue()
        cels = round((fahr - 32) * 5 / 9.0, 2)
        self.celsius.SetLabel(str(cels))

def main():

    ex = wx.App()
    Example(None)
    ex.MainLoop()

if __name__ == '__main__':
    main()

wx.SpinCtrl

A wx.ListBox widget

import wx

ID_NEW = 1
ID_RENAME = 2
ID_CLEAR = 3
ID_DELETE = 4


class ListBox(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title, size=(350, 220))

        panel = wx.Panel(self, -1)
        hbox = wx.BoxSizer(wx.HORIZONTAL)

        self.listbox = wx.ListBox(panel, -1)
        hbox.Add(self.listbox, 1, wx.EXPAND | wx.ALL, 20)

        btnPanel = wx.Panel(panel, -1)
        vbox = wx.BoxSizer(wx.VERTICAL)
        new = wx.Button(btnPanel, ID_NEW, 'New', size=(90, 30))
        ren = wx.Button(btnPanel, ID_RENAME, 'Rename', size=(90, 30))
        dlt = wx.Button(btnPanel, ID_DELETE, 'Delete', size=(90, 30))
        clr = wx.Button(btnPanel, ID_CLEAR, 'Clear', size=(90, 30))

        self.Bind(wx.EVT_BUTTON, self.NewItem, id=ID_NEW)
        self.Bind(wx.EVT_BUTTON, self.OnRename, id=ID_RENAME)
        self.Bind(wx.EVT_BUTTON, self.OnDelete, id=ID_DELETE)
        self.Bind(wx.EVT_BUTTON, self.OnClear, id=ID_CLEAR)
        self.Bind(wx.EVT_LISTBOX_DCLICK, self.OnRename)

        vbox.Add((-1, 20))
        vbox.Add(new)
        vbox.Add(ren, 0, wx.TOP, 5)
        vbox.Add(dlt, 0, wx.TOP, 5)
        vbox.Add(clr, 0, wx.TOP, 5)

        btnPanel.SetSizer(vbox)
        hbox.Add(btnPanel, 0.6, wx.EXPAND | wx.RIGHT, 20)
        panel.SetSizer(hbox)

        self.Centre()
        self.Show(True)

    def NewItem(self, event):
        text = wx.GetTextFromUser('Enter a new item', 'Insert dialog')
        if text != '':
            self.listbox.Append(text)

    def OnRename(self, event):
        sel = self.listbox.GetSelection()
        text = self.listbox.GetString(sel)
        renamed = wx.GetTextFromUser('Rename item', 'Rename dialog', text)
        if renamed != '':
            self.listbox.Delete(sel)
            self.listbox.Insert(renamed, sel)


    def OnDelete(self, event):
        sel = self.listbox.GetSelection()
        if sel != -1:
            self.listbox.Delete(sel)

    def OnClear(self, event):
        self.listbox.Clear()


app = wx.App()
ListBox(None, -1, 'ListBox')
app.MainLoop()

wx.ListBox widget

A wx.html.HtmlWindow widget

import wx
import wx.html as html

ID_CLOSE = 1

page = '<html><body bgcolor="#8e8e95"><table cellspacing="5" border="0" width="250"> \
<tr width="200" align="left"> \
<td bgcolor="#e7e7e7">&nbsp;&nbsp;Maximum</td> \
<td bgcolor="#aaaaaa">&nbsp;&nbsp;<b>9000</b></td> \
</tr> \
<tr align="left"> \
<td bgcolor="#e7e7e7">&nbsp;&nbsp;Mean</td> \
<td bgcolor="#aaaaaa">&nbsp;&nbsp;<b>6076</b></td> \
</tr> \
<tr align="left"> \
<td bgcolor="#e7e7e7">&nbsp;&nbsp;Minimum</td> \
<td bgcolor="#aaaaaa">&nbsp;&nbsp;<b>3800</b></td> \
</tr> \
<tr align="left"> \
<td bgcolor="#e7e7e7">&nbsp;&nbsp;Median</td> \
<td bgcolor="#aaaaaa">&nbsp;&nbsp;<b>6000</b></td> \
</tr> \
<tr align="left"> \
<td bgcolor="#e7e7e7">&nbsp;&nbsp;Standard Deviation</td> \
<td bgcolor="#aaaaaa">&nbsp;&nbsp;<b>6076</b></td> \
</tr> \
</body></table></html>'


class MyFrame(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title, size=(400, 290))

        panel = wx.Panel(self, -1)

        vbox = wx.BoxSizer(wx.VERTICAL)
        hbox = wx.BoxSizer(wx.HORIZONTAL)

        htmlwin = html.HtmlWindow(panel, -1, style=wx.NO_BORDER)
        htmlwin.SetBackgroundColour(wx.RED)
        htmlwin.SetStandardFonts()
        htmlwin.SetPage(page)

        vbox.Add((-1, 10), 0)
        vbox.Add(htmlwin, 1, wx.EXPAND | wx.ALL, 9)

        bitmap = wx.StaticBitmap(panel, -1, wx.Bitmap('images/newt.png'))
        hbox.Add(bitmap, 1, wx.LEFT | wx.BOTTOM | wx.TOP, 10)
        buttonOk = wx.Button(panel, ID_CLOSE, 'Ok')

        self.Bind(wx.EVT_BUTTON, self.OnClose, id=ID_CLOSE)

        hbox.Add((100, -1), 1, wx.EXPAND | wx.ALIGN_RIGHT)
        hbox.Add(buttonOk, flag=wx.TOP | wx.BOTTOM | wx.RIGHT, border=10)
        vbox.Add(hbox, 0, wx.EXPAND)

        panel.SetSizer(vbox)
        self.Centre()
        self.Show(True)

    def OnClose(self, event):
        self.Close()

app = wx.App(0)
MyFrame(None, -1, 'Basic Statistics')
app.MainLoop()

Help window

A wx.ListCtrl widget

Reader

CheckListCtrl

Drag and drop in wxPython

wx.TextDropTarget


import os
import wx

class MyTextDropTarget(wx.TextDropTarget):
    def __init__(self, object):
        wx.TextDropTarget.__init__(self)
        self.object = object

    def OnDropText(self, x, y, data):
        self.object.InsertStringItem(0, data)


class DragDrop(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title, size=(650, 500))

        splitter1 = wx.SplitterWindow(self, -1, style=wx.SP_3D)
        splitter2 = wx.SplitterWindow(splitter1, -1, style=wx.SP_3D)
        self.dir = wx.GenericDirCtrl(splitter1, -1, dir='c://tmp//', style=wx.DIRCTRL_DIR_ONLY)
        self.lc1 = wx.ListCtrl(splitter2, -1, style=wx.LC_LIST)
        self.lc2 = wx.ListCtrl(splitter2, -1, style=wx.LC_LIST)

        dt = MyTextDropTarget(self.lc2)
        self.lc2.SetDropTarget(dt)
        self.Bind(wx.EVT_LIST_BEGIN_DRAG, self.OnDragInit, id=self.lc1.GetId())

        tree = self.dir.GetTreeCtrl()

        splitter2.SplitHorizontally(self.lc1, self.lc2)
        splitter1.SplitVertically(self.dir, splitter2)

        self.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnSelect, id=tree.GetId())

        self.OnSelect(0)
        self.Centre()
        self.Show(True)

    def OnSelect(self, event):
        list = os.listdir(self.dir.GetPath())
        self.lc1.ClearAll()
        self.lc2.ClearAll()
        for i in range(len(list)):
            if list[i][0] != '.':
                self.lc1.InsertStringItem(0, list[i])

    def OnDragInit(self, event):
        text = self.lc1.GetItemText(event.GetIndex())
        tdo = wx.TextDataObject(text)
        tds = wx.DropSource(self.lc1)
        tds.SetData(tdo)
        tds.DoDragDrop(True)


app = wx.App()
DragDrop(None, -1, 'dragdrop.py')
app.MainLoop()

Text drag and drop

參考資料:http://zetcode.com/wxpython/

回主目錄

 

 

 

 

 

文章標籤

stanley 發表在 痞客邦 留言(0) 人氣()

使用wxPython 模組去記錄視窗程式設計-第二篇(位置篇)

目前使用的環境:windows 7、Portable Python 2.7.6.1、wxPython 3.0
這章將加入更多元件例子,我只寫程式碼,複製程式碼執行可以看到測試結果,
如此方便學習及加速開發程式時間,但
更多說明要自己參考下面的參考文件。

(1) Layout management
Layout 管理在是
視窗程式設計不容易的,有兩種方式使用絕對位置及可大小變化的相對位置

(1.1)使用絕對位置視窗

# -*- coding: big5 -*-
#-------------------------------------------------------------------------------
# absolute.py
import wx
class absolute(wx.Frame):

    def __init__(self, parent, title):
        super(absolute, self).__init__(parent, title='絕對位置視窗',
            size=(260, 180))

        self.InitUI()
        self.Centre()
        self.Show()

    def InitUI(self):

        panel = wx.Panel(self, -1)
        menubar = wx.MenuBar()
        filem = wx.Menu()
        editm = wx.Menu()
        helpm = wx.Menu()

        menubar.Append(filem, '&檔案')
        menubar.Append(editm, '&編輯')
        menubar.Append(helpm, '&幫助')
        self.SetMenuBar(menubar)

        wx.TextCtrl(panel, pos=(3, 3), size=(250, 150))


if __name__ == '__main__':

    app = wx.App()
    absolute(None, title='')
    app.MainLoop()

absolute positioning 1

#-------------------------

(1.2)使用.wx.frame內建的相對位置

# -*- coding: big5 -*-
#-------------------------
# sizer.py
#-------------------------

import wx

class Example(wx.Frame):

    def __init__(self, parent, title):
        super(Example, self).__init__(parent, title='相對位置視窗',
            size=(260, 180))

        self.InitUI()
        self.Centre()
        self.Show()

    def InitUI(self):

        menubar = wx.MenuBar()
        filem = wx.Menu()
        editm = wx.Menu()
        helpm = wx.Menu()

        menubar.Append(filem, '&檔案')
        menubar.Append(editm, '&編輯')
        menubar.Append(helpm, '&幫助')
        self.SetMenuBar(menubar)

        wx.TextCtrl(self)


if __name__ == '__main__':

    app = wx.App()
    Example(None, title='')
    app.MainLoop()

absolute positioning 2

Using sizers

  • wx.BoxSizer
  • wx.StaticBoxSizer
  • wx.GridSizer
  • wx.FlexGridSizer
  • wx.GridBagSizer

-------------------------
(1.3)使用wx.BoxSizer 相對位置視窗

# -*- coding: big5 -*-
#-------------------------
# box = wx.BoxSizer(integer orient)
# box.Add(wx.Window window, integer proportion=0, integer flag = 0, integer border = 0)
#-------------------------
# border.py
# Border around a panel
import wx

class Example(wx.Frame):

    def __init__(self, parent, title):
        super(Example, self).__init__(parent, title=title,
            size=(260, 180))

        self.InitUI()
        self.Centre()
        self.Show()

    def InitUI(self):

        panel = wx.Panel(self)

        panel.SetBackgroundColour('#4f5049') #設定大panel背景顏色
        vbox = wx.BoxSizer(wx.VERTICAL)      #方向可以是 wx.VERTICAL or wx.HORIZONTAL
        midPan = wx.Panel(panel)
        midPan.SetBackgroundColour('#ededed') #設定小panel背景顏色

        vbox.Add(midPan, 1, wx.EXPAND | wx.ALL, 20) # 20 px border around a midPan panel.
        panel.SetSizer(vbox)                        # flag = wx.EXPAND| wx.ALL 組合邊界至四個邊

if __name__ == '__main__':

    app = wx.App()
    Example(None, title='Border')
    app.MainLoop()

Border around a panel

#-------------------------

Box = wx.BoxSizer(wxHORIZONTAL)
Box = wx.BoxSizer(wxVERTICAL) 
Box.Add(control, proportion, flag, border)

 

Alignment Flags

wx.ALIGN_TOP
wx.ALIGN_BOTTOM
wx.ALIGN_LEFT
wx.ALIGN_RIGHT
wx.ALIGN_CENTER_VERTICAL
wx.ALIGN_CENTER_HORIZONTAL

Border Flags

wx.TOP
wx.BOTTOM
wx.LEFT
wx.RIGHT
wx.ALL

Behavior Flags

S.N. Behavior Flags & Description
1

wx.EXPAND

Item will expand to fill the space provided to it (wx.GROW is the same)

2

wx.SHAPED

Similar to EXPAND but maintains the item's aspect ratio

3

wx.FIXED_MINSIZE

Does not let the item become smaller than its initial minimum size

4

wx.RESERVE_SPACE_EVEN_IF_ HIDDEN

Does not allow the sizer to reclaim an item's space when it is hidden

另一個例子 

class BoxSizerPanel(wx.Panel):
def __init__(self, parent, *args, **kwargs):
        super(BoxSizerPanel, self).__init__(*args, **kwargs)

        # Attributes
        self._field1 = wx.TextCtrl(self)
        self._field2 = wx.TextCtrl(self)

        # Layout
        self._DoLayout()

def _DoLayout(self):
    vsizer = wx.BoxSizer(wx.VERTICAL)
    field1_sz = wx.BoxSizer(wx.HORIZONTAL)
    field2_sz = wx.BoxSizer(wx.HORIZONTAL)

    # 兩個 labels
    field1_lbl = wx.StaticText(self, label="Field 1:")
    field2_lbl = wx.StaticText(self, label="Field 2:")

    # label and field 加至第一個水平box
   field1_sz.AddSpacer(50) #增加50 px 空白
    field1_sz.Add(field1_lbl) #加入label 1
    field1_sz.AddSpacer(5) #增加 5px 空白
    field1_sz.Add(self._field1) #加入field 1
    field1_sz.AddSpacer(50)
  
   # label and field 加至第二個水平box
    field2_sz.AddSpacer(50)
    field2_sz.Add(field2_lbl)
    field2_sz.AddSpacer(5)
    field2_sz.Add(self._field2)
    field2_sz.AddSpacer(50)

    # 增加二個水平box 至一個較大的直box
    vsizer.AddSpacer(50)
    vsizer.Add(field1_sz)
    vsizer.AddSpacer(15)
    vsizer.Add(field2_sz)
    vsizer.AddSpacer(50)

    # 指定主要外層box 至panel
    self.SetSizer(vsizer)


更多位置管理請參考 http://zetcode.com/wxpython/layout/

https://www.tutorialspoint.com/wxpython/wx_boxsizer.htm

 

wx.GridSizer

Calculator

wx.FlexGridSizer

Review

wx.GridBagSizer

(2) Menus and toolbars

# -*- coding: big5 -*-
#-------------------------

import wx

class Example(wx.Frame):

    def __init__(self, *args, **kwargs):
        super(Example, self).__init__(*args, **kwargs)

        self.InitUI()

    def InitUI(self):

        menubar = wx.MenuBar()  #增加一個 menubar類別

        fileMenu = wx.Menu()    #增加一個 submenu類別
        fitem = fileMenu.Append(wx.ID_EXIT, 'Quit', 'Quit application') #subitem 內容
        menubar.Append(fileMenu, '&File') # submenu 內容
        self.SetMenuBar(menubar)

        self.Bind(wx.EVT_MENU, self.OnQuit, fitem)

        self.SetSize((300, 200))
        self.SetTitle('Simple menu')
        self.Centre()
        self.Show(True)

    def OnQuit(self, e):
        self.Close()

def main():

    ex = wx.App()
    Example(None)
    ex.MainLoop()

if __name__ == '__main__':
    main()

A simple menu example

Toolbars

import wx

class Example(wx.Frame):

    def __init__(self, *args, **kwargs):
        super(Example, self).__init__(*args, **kwargs)

        self.InitUI()

    def InitUI(self):

        toolbar = self.CreateToolBar()
        qtool = toolbar.AddLabelTool(wx.ID_ANY, 'Quit', wx.Bitmap('texit.png'))
        toolbar.Realize()

        self.Bind(wx.EVT_TOOL, self.OnQuit, qtool)

        self.SetSize((250, 200))
        self.SetTitle('Simple toolbar')
        self.Centre()
        self.Show(True)

    def OnQuit(self, e):
        self.Close()

def main():

    ex = wx.App()
    Example(None)
    ex.MainLoop()


if __name__ == '__main__':
    main()

Simple toolbar

(3)Simple Events
 事件處理步驟

(1) 事件類型
(2) 事件處理程式
(3) 連結事件型和事件處理程式

(3.1) Simple Events 設定及動作

# -*- coding: big5 -*-
#-------------------------

import wx

class Example(wx.Frame):

    def __init__(self, *args, **kw):
        super(Example, self).__init__(*args, **kw)

        self.InitUI()


    def InitUI(self):

        wx.StaticText(self, label='x:', pos=(10,10))
        wx.StaticText(self, label='y:', pos=(10,30))

        self.st1 = wx.StaticText(self, label='', pos=(30, 10))
        self.st2 = wx.StaticText(self, label='', pos=(30, 30))

        self.Bind(wx.EVT_MOVE, self.OnMove)  # 事件監聽(event type, event handle)

        self.SetSize((250, 180))
        self.SetTitle('Move event')
        self.Centre()
        self.Show(True)

    def OnMove(self, e):
        x, y = e.GetPosition()
        self.st1.SetLabel(str(x))
        self.st2.SetLabel(str(y))


def main():

    ex = wx.App()
    Example(None)
    ex.MainLoop()


if __name__ == '__main__':
    main()

 

(3.2)Events 傳遞 in wxPython

事件有二種類型,基本事件及命令事件,基本事件不會傳遞,命令事件會從子類別傳給父類別,祖類別直到有事件處理者接手才會停止傳遞
另外  Veto() method 可以停止Event, Skip() method 可以跳開傳遞

 # -*- coding: big5 -*-
#-------------------------

import wx

class MyPanel(wx.Panel):

    def __init__(self, *args, **kw):
        super(MyPanel, self).__init__(*args, **kw)

        self.Bind(wx.EVT_BUTTON, self.OnButtonClicked)

    def OnButtonClicked(self, e):

        print 'event reached panel class'
        e.Skip()


class MyButton(wx.Button):

    def __init__(self, *args, **kw):
        super(MyButton, self).__init__(*args, **kw)

        self.Bind(wx.EVT_BUTTON, self.OnButtonClicked)  # 事件監聽

    def OnButtonClicked(self, e):

        print 'event reached button class'
        e.Skip()


class Example(wx.Frame):

    def __init__(self, *args, **kw):
        super(Example, self).__init__(*args, **kw)

        self.InitUI()


    def InitUI(self):

        mpnl = MyPanel(self)

        MyButton(mpnl, label='Ok', pos=(15, 15))

        self.Bind(wx.EVT_BUTTON, self.OnButtonClicked)

        self.SetTitle('Propagate event')
        self.Centre()
        self.Show(True)

    def OnButtonClicked(self, e):

        print 'event reached frame class'
        e.Skip()


def main():

    ex = wx.App()
    Example(None)
    ex.MainLoop()


if __name__ == '__main__':
    main()

#-----------------------------
這個應用程式有 app ->frame -> Panel -> Button , 所以事件發生在 button, button 事件處理者傳遞事件,所以傳遞路徑是 button-> panel -> frame 
#---------------------------

 

參考資料

http://zetcode.com/wxpython/

回主目錄

stanley 發表在 痞客邦 留言(0) 人氣()

«12 3
Close

您尚未登入,將以訪客身份留言。亦可以上方服務帳號登入留言

請輸入暱稱 ( 最多顯示 6 個中文字元 )

請輸入標題 ( 最多顯示 9 個中文字元 )

請輸入內容 ( 最多 140 個中文字元 )

reload

請輸入左方認證碼:

看不懂,換張圖

請輸入驗證碼