python變數鎖
1. python多線程全局變數和鎖
1.python中數據類型,int,float,復數,字元,元組,做全局變數時需要在函數裡面用global申明變數,才能對變數進行操作。
而,對象,列表,詞典,不需要聲明,直接就是全局的。
2.線程鎖mutex=threading.Lock()
創建後就是全局的。線程調用函數可以直接在函數中使用。
mutex.acquire()開啟鎖
mutex=release()關閉鎖
要注意,死鎖的情況發生。
注意運行效率的變化:
正常1秒,完成56997921
加鎖之後,1秒只運行了531187,相差10倍多。
3.繼承.threading.Thread的類,無法調用__init__函數,無法在創建對象時初始化新建的屬性。
4.線程在cpu的執行,有隨機性
5. 新建線程時,需要傳參數時,args是一個元組,如果只有一個參數,一定後面要加一個,符號。不能只有一個參數否則線程會報創建參數錯誤。threading.Thread(target=fuc,args=(arg,))
2. python多個線程鎖可提高效率嗎
首先,Python的多線程本身就是效率極低的,因為有GIL(Global Interpreter Lock:全局解釋鎖)機制的限制,其作用簡單說就是:對於一個解釋器,只能有一個線程在執行bytecode。
所以如果為了追求傳統意義上多線程的效率,在Python界還是用多進程(multiprocessing)吧……
這里你用了多線程,且用了鎖來控制公共資源,首先鎖這個東西會導致死鎖,不加鎖反而沒有死鎖隱患,但會有同步問題。
另外,如果不同線程操作的是不同的文件,是不存在同步問題的,如果操作同一個文件,我建議採用Queue(隊列)來處理。
總的來說,用單線程就好了,因為Python多線程本身就沒什麼效率,而且單線程也不用考慮同步問題了。非要追求效率的話,就用多進程吧,同樣也要考慮進程鎖。
3. Python為什麼要有全局鎖
多進程和多線程 需要鎖,不然會造成輸出結果錯亂。比如:同時print("hello world!"),會造成這樣的結果:hehello worldllo world,會同時列印在一起。鎖是避免出現這種情況。
4. Python中的各種鎖
大致羅列一下:
一、全局解釋器鎖(GIL)
1、什麼是全局解釋器鎖
每個CPU在同一時間只能執行一個線程,那麼其他的線程就必須等待該線程的全局解釋器,使用權消失後才能使用全局解釋器,即使多個線程直接不會相互影響在同一個進程下也只有一個線程使用cpu,這樣的機制稱為全局解釋器鎖(GIL)。GIL的設計簡化了CPython的實現,使的對象模型包括關鍵的內建類型,如:字典等,都是隱含的,可以並發訪問的,鎖住全局解釋器使得比較容易的實現對多線程的支持,但也損失了多處理器主機的並行計算能力。
2、全局解釋器鎖的好處
1)、避免了大量的加鎖解鎖的好處
2)、使數據更加安全,解決多線程間的數據完整性和狀態同步
3、全局解釋器的缺點
多核處理器退化成單核處理器,只能並發不能並行。
4、GIL的作用:
多線程情況下必須存在資源的競爭,GIL是為了保證在解釋器級別的線程唯一使用共享資源(cpu)。
二、同步鎖
1、什麼是同步鎖?
同一時刻的一個進程下的一個線程只能使用一個cpu,要確保這個線程下的程序在一段時間內被cpu執,那麼就要用到同步鎖。
2、為什麼用同步鎖?
因為有可能當一個線程在使用cpu時,該線程下的程序可能會遇到io操作,那麼cpu就會切到別的線程上去,這樣就有可能會影響到該程序結果的完整性。
3、怎麼使用同步鎖?
只需要在對公共數據的操作前後加上上鎖和釋放鎖的操作即可。
4、同步鎖的所用:
為了保證解釋器級別下的自己編寫的程序唯一使用共享資源產生了同步鎖。
三、死鎖
1、什麼是死鎖?
指兩個或兩個以上的線程或進程在執行程序的過程中,因爭奪資源或者程序推進順序不當而相互等待的一個現象。
2、死鎖產生的必要條件?
互斥條件、請求和保持條件、不剝奪條件、環路等待條件
3、處理死鎖的基本方法?
預防死鎖、避免死鎖(銀行家演算法)、檢測死鎖(資源分配)、解除死鎖:剝奪資源、撤銷進程
四、遞歸鎖
在Python中為了支持同一個線程中多次請求同一資源,Python提供了可重入鎖。這個RLock內部維護著一個Lock和一個counter變數,counter記錄了acquire的次數,從而使得資源可以被多次require。直到一個線程所有的acquire都被release,其他的線程才能獲得資源。遞歸鎖分為可遞歸鎖與非遞歸鎖。
五、樂觀鎖
假設不會發生並發沖突,只在提交操作時檢查是否違反數據完整性。
六、悲觀鎖
假定會發生並發沖突,屏蔽一切可能違反數據完整性的操作。
python常用的加鎖方式:互斥鎖、可重入鎖、迭代死鎖、互相調用死鎖、自旋鎖。
5. python有哪些特點和優點
顯著的優點
Python 語言擁有諸多的優點,這其中,以下幾個優點特別顯著:
簡單易學:Python語言相對於其他編程語言來說,屬於比較容易學習的一門編程語言,它注重的是如何解決問題而不是編程語言的語法和結構。正是因為Python語言簡單易學,所以,已經有越來越多的初學者選擇Python語言作為編程的入門語言。例如,在浙江省 2017年高中信息技術改革中,《演算法與程序設計》課程將使用 Python語言替換原有的VB 語言。
語法優美:Python語言力求代碼簡潔、優美。在Python語言中,採用縮進來標識代碼塊,通過減少無用的大括弧,去除語句末尾的分號等視覺雜訊,使得代碼的可讀性顯著提高。閱讀一段良好的Python程序就感覺像是在讀英語一樣,它使你能夠專注於解決問題,而不用太糾結編程語言本身的語法。
豐富強大的庫:Python語言號稱自帶電池(Battery Included),寓意是Python語言的類庫非常的全面,包含了解決各種問題的類庫。無論實現什麼功能,都有現成的類庫可以使用。如果一個功能比較特殊,標准庫沒有提供相應的支持,那麼,很大概率也會有相應的開源項目提供了類似的功能。合理使用Python的類庫和開源項目,能夠快速的實現功能,滿足業務需求。
開發效率高:Python的各個優點是相輔相成的。例如,Python語言因為有了豐富強大的類庫,所以,Python的開發效率能夠顯著提高。相對於 C、C++ 和 Java等編譯語言,Python開發者的效率提高了數倍。實現相同的功能,Python代碼的文件往往只有 C、C++和Java代碼的1/5~1/3。雖然Python語言擁有很多吸引人的特性,但是,各大互聯網公司廣泛使用Python語言,很大程度上是因為Python語言開發效率高這個特點。開發效率高的語言,能夠更好的滿足互聯網快速迭代的需求,因此,Python語言在互聯網公司使用非常廣泛。
應用領域廣泛:Python語言的另一大優點就是應用領域廣泛,工程師可以使用Python 做很多的事情。例如,Web開發、網路編程、自動化運維、Linux系統管理、數據分析、科學計算、人工智慧、機器學習等等。Python語言介於腳本語言和系統語言之間,我們根據需要,既可以將它當做一門腳本語言來編寫腳本,也可以將它當做一個系統語言來編寫服務。
不可忽視的缺點
毫無疑問,Python確實有用很多的優點,每一個優點看起來都非常吸引人。但是,Python並不是沒有缺點的,最主要的缺點有以下幾個:
Python的執行速度不夠快。當然,這也不是一個很嚴重的問題,一般情況下,我們不會拿Python語言與C/C++這樣的語言進行直接比較。在Python語言的執行速度上,一方面,網路或磁碟的延遲,會抵消掉部分Python本身消耗的時間;另一方面,因為Python 特別容易和C結合起來,因此,我們可以通過分離一部分需要優化速度的應用,將其轉換為編譯好的擴展,並在整個系統中使用Python腳本將這部分應用連接起來,以提高程序的整體效率。
Python的GIL鎖限制並發:Python的另一個大問題是,對多處理器支持不好。如果讀者接觸Python時間比較長,那麼,一定聽說過GIL這個詞。GIL是指Python全局解釋器鎖(Global Interpreter Lock),當Python的默認解釋器要執行位元組碼時,都需要先申請這個鎖。這意味著,如果試圖通過多線程擴展應用程序,將總是被這個全局解釋器鎖限制。當然,我們可以使用多進程的架構來提高程序的並發,也可以選擇不同的Python實現來運行我們的程序。
Python 2與Python 3不兼容: 如果一個普通的軟體或者庫,不能夠做到後向兼容,那麼,它會被用戶無情的拋棄了。在Python中,一個槽點是Python 2與Python 3不兼容。因為Python沒有向後兼容,給所有的Python工程師帶來了無數的煩惱。
上述就是總結的Python語言的優缺點。總體來說,Python目前的發展還是非常不錯的。借著人工智慧時代的東風,Python開發人員的未來一定會很光明。
6. 深入解析Python中的線程同步方法
深入解析Python中的線程同步方法
同步訪問共享資源
在使用線程的時候,一個很重要的問題是要避免多個線程對同一變數或其它資源的訪問沖突。一旦你稍不留神,重疊訪問、在多個線程中修改(共享資源)等這些操作會導致各種各樣的問題;更嚴重的是,這些問題一般只會在比較極端(比如高並發、生產伺服器、甚至在性能更好的硬體設備上)的情況下才會出現。
比如有這樣一個情況:需要追蹤對一事件處理的次數
counter = 0
def process_item(item):
global counter
... do something with item ...
counter += 1
如果你在多個線程中同時調用這個函數,你會發現counter的值不是那麼准確。在大多數情況下它是對的,但有時它會比實際的少幾個。
出現這種情況的原因是,計數增加操作實際上分三步執行:
解釋器獲取counter的當前值計算新值將計算的新值回寫counter變數
考慮一下這種情況:在當前線程獲取到counter值後,另一個線程搶佔到了CPU,然後同樣也獲取到了counter值,並進一步將counter值重新計算並完成回寫;之後時間片重新輪到當前線程(這里僅作標識區分,並非實際當前),此時當前線程獲取到counter值還是原來的,完成後續兩步操作後counter的值實際只加上1。
另一種常見情況是訪問不完整或不一致狀態。這類情況主要發生在一個線程正在初始化或更新數據時,另一個進程卻嘗試讀取正在更改的數據。
原子操作
實現對共享變數或其它資源的同步訪問最簡單的方法是依靠解釋器的原子操作。原子操作是在一步完成執行的操作,在這一步中其它線程無法獲得該共享資源。
通常情況下,這種同步方法只對那些只由單個核心數據類型組成的共享資源有效,譬如,字元串變數、數字、列表或者字典等。下面是幾個線程安全的操作:
讀或者替換一個實例屬性讀或者替換一個全局變數從列表中獲取一項元素原位修改一個列表(例如:使用append增加一個列表項)從字典中獲取一項元素原位修改一個字典(例如:增加一個字典項、調用clear方法)
注意,上面提到過,對一個變數或者屬性進行讀操作,然後修改它,最終將其回寫不是線程安全的。因為另外一個線程會在這個線程讀完卻沒有修改或回寫完成之前更改這個共享變數/屬性。
鎖
鎖是Python的threading模塊提供的最基本的同步機制。在任一時刻,一個鎖對象可能被一個線程獲取,或者不被任何線程獲取。如果一個線程嘗試去獲取一個已經被另一個線程獲取到的鎖對象,那麼這個想要獲取鎖對象的線程只能暫時終止執行直到鎖對象被另一個線程釋放掉。
鎖通常被用來實現對共享資源的同步訪問。為每一個共享資源創建一個Lock對象,當你需要訪問該資源時,調用acquire方法來獲取鎖對象(如果其它線程已經獲得了該鎖,則當前線程需等待其被釋放),待資源訪問完後,再調用release方法釋放鎖:
lock = Lock()
lock.acquire() #: will block if lock is already held
... access shared resource
lock.release()
注意,即使在訪問共享資源的過程中出錯了也應該釋放鎖,可以用try-finally來達到這一目的:
lock.acquire()
try:
... access shared resource
finally:
lock.release() #: release lock, no matter what
在Python 2.5及以後的版本中,你可以使用with語句。在使用鎖的時候,with語句會在進入語句塊之前自動的獲取到該鎖對象,然後在語句塊執行完成後自動釋放掉鎖:
from __future__ import with_statement #: 2.5 only
with lock:
... access shared resource
acquire方法帶一個可選的等待標識,它可用於設定當有其它線程佔有鎖時是否阻塞。如果你將其值設為False,那麼acquire方法將不再阻塞,只是如果該鎖被佔有時它會返回False:
if not lock.acquire(False):
... 鎖資源失敗
else:
try:
... access shared resource
finally:
lock.release()
你可以使用locked方法來檢查一個鎖對象是否已被獲取,注意不能用該方法來判斷調用acquire方法時是否會阻塞,因為在locked方法調用完成到下一條語句(比如acquire)執行之間該鎖有可能被其它線程佔有。
if not lock.locked():
#: 其它線程可能在下一條語句執行之前佔有了該鎖
lock.acquire() #: 可能會阻塞
簡單鎖的缺點
標準的鎖對象並不關心當前是哪個線程佔有了該鎖;如果該鎖已經被佔有了,那麼任何其它嘗試獲取該鎖的線程都會被阻塞,即使是佔有鎖的這個線程。考慮一下下面這個例子:
lock = threading.Lock()
def get_first_part():
lock.acquire()
try:
... 從共享對象中獲取第一部分數據
finally:
lock.release()
return data
def get_second_part():
lock.acquire()
try:
... 從共享對象中獲取第二部分數據
finally:
lock.release()
return data
示例中,我們有一個共享資源,有兩個分別取這個共享資源第一部分和第二部分的函數。兩個訪問函數都使用了鎖來確保在獲取數據時沒有其它線程修改對應的共享數據。
現在,如果我們想添加第三個函數來獲取兩個部分的數據,我們將會陷入泥潭。一個簡單的方法是依次調用這兩個函數,然後返回結合的結果:
def get_both_parts():
first = get_first_part()
seconde = get_second_part()
return first, second
這里的問題是,如有某個線程在兩個函數調用之間修改了共享資源,那麼我們最終會得到不一致的數據。最明顯的解決方法是在這個函數中也使用lock:
def get_both_parts():
lock.acquire()
try:
first = get_first_part()
seconde = get_second_part()
finally:
lock.release()
return first, second
然而,這是不可行的。裡面的兩個訪問函數將會阻塞,因為外層語句已經佔有了該鎖。為了解決這個問題,你可以通過使用標記在訪問函數中讓外層語句釋放鎖,但這樣容易失去控制並導致出錯。幸運的是,threading模塊包含了一個更加實用的鎖實現:re-entrant鎖。
Re-Entrant Locks (RLock)
RLock類是簡單鎖的另一個版本,它的特點在於,同一個鎖對象只有在被其它的線程佔有時嘗試獲取才會發生阻塞;而簡單鎖在同一個線程中同時只能被佔有一次。如果當前線程已經佔有了某個RLock鎖對象,那麼當前線程仍能再次獲取到該RLock鎖對象。
lock = threading.Lock()
lock.acquire()
lock.acquire() #: 這里將會阻塞
lock = threading.RLock()
lock.acquire()
lock.acquire() #: 這里不會發生阻塞
RLock的主要作用是解決嵌套訪問共享資源的問題,就像前面描述的示例。要想解決前面示例中的問題,我們只需要將Lock換為RLock對象,這樣嵌套調用也會OK.
lock = threading.RLock()
def get_first_part():
... see above
def get_second_part():
... see above
def get_both_parts():
... see above
這樣既可以單獨訪問兩部分數據也可以一次訪問兩部分數據而不會被鎖阻塞或者獲得不一致的數據。
注意RLock會追蹤遞歸層級,因此記得在acquire後進行release操作。
Semaphores
信號量是一個更高級的鎖機制。信號量內部有一個計數器而不像鎖對象內部有鎖標識,而且只有當佔用信號量的線程數超過信號量時線程才阻塞。這允許了多個線程可以同時訪問相同的代碼區。
semaphore = threading.BoundedSemaphore()
semaphore.acquire() #: counter減小
... 訪問共享資源
semaphore.release() #: counter增大
當信號量被獲取的時候,計數器減小;當信號量被釋放的時候,計數器增大。當獲取信號量的時候,如果計數器值為0,則該進程將阻塞。當某一信號量被釋放,counter值增加為1時,被阻塞的線程(如果有的話)中會有一個得以繼續運行。
信號量通常被用來限制對容量有限的資源的訪問,比如一個網路連接或者資料庫伺服器。在這類場景中,只需要將計數器初始化為最大值,信號量的實現將為你完成剩下的事情。
max_connections = 10
semaphore = threading.BoundedSemaphore(max_connections)
如果你不傳任何初始化參數,計數器的值會被初始化為1.
Python的threading模塊提供了兩種信號量實現。Semaphore類提供了一個無限大小的信號量,你可以調用release任意次來增大計數器的值。為了避免錯誤出現,最好使用BoundedSemaphore類,這樣當你調用release的次數大於acquire次數時程序會出錯提醒。
線程同步
鎖可以用在線程間的同步上。threading模塊包含了一些用於線程間同步的類。
Events
一個事件是一個簡單的同步對象,事件表示為一個內部標識(internal flag),線程等待這個標識被其它線程設定,或者自己設定、清除這個標識。
event = threading.Event()
#: 一個客戶端線程等待flag被設定
event.wait()
#: 服務端線程設置或者清除flag
event.set()
event.clear()
一旦標識被設定,wait方法就不做任何處理(不會阻塞),當標識被清除時,wait將被阻塞直至其被重新設定。任意數量的線程可能會等待同一個事件。
Conditions
條件是事件對象的高級版本。條件表現為程序中的某種狀態改變,線程可以等待給定條件或者條件發生的信號。
下面是一個簡單的生產者/消費者實例。首先你需要創建一個條件對象:
#: 表示一個資源的附屬項
condition = threading.Condition()
生產者線程在通知消費者線程有新生成資源之前需要獲得條件:
#: 生產者線程
... 生產資源項
condition.acquire()
... 將資源項添加到資源中
condition.notify() #: 發出有可用資源的信號
condition.release()
消費者必須獲取條件(以及相關聯的鎖),然後嘗試從資源中獲取資源項:
#: 消費者線程
condition.acquire()
while True:
...從資源中獲取資源項
if item:
break
condition.wait() #: 休眠,直至有新的資源
condition.release()
... 處理資源
wait方法釋放了鎖,然後將當前線程阻塞,直到有其它線程調用了同一條件對象的notify或者notifyAll方法,然後又重新拿到鎖。如果同時有多個線程在等待,那麼notify方法只會喚醒其中的一個線程,而notifyAll則會喚醒全部線程。
為了避免在wait方法處阻塞,你可以傳入一個超時參數,一個以秒為單位的浮點數。如果設置了超時參數,wait將會在指定時間返回,即使notify沒被調用。一旦使用了超時,你必須檢查資源來確定發生了什麼。
注意,條件對象關聯著一個鎖,你必須在訪問條件之前獲取這個鎖;同樣的,你必須在完成對條件的訪問時釋放這個鎖。在生產代碼中,你應該使用try-finally或者with.
可以通過將鎖對象作為條件構造函數的參數來讓條件關聯一個已經存在的鎖,這可以實現多個條件公用一個資源:
lock = threading.RLock()
condition_1 = threading.Condition(lock)
condition_2 = threading.Condition(lock)
互斥鎖同步
我們先來看一個例子:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import time, threading
# 假定這是你的銀行存款:
balance = 0
muxlock = threading.Lock()
def change_it(n):
# 先存後取,結果應該為0:
global balance
balance = balance + n
balance = balance - n
def run_thread(n):
# 循環次數一旦多起來,最後的數字就變成非0
for i in range(100000):
change_it(n)
t1 = threading.Thread(target=run_thread, args=(5,))
t2 = threading.Thread(target=run_thread, args=(8,))
t3 = threading.Thread(target=run_thread, args=(9,))
t1.start()
t2.start()
t3.start()
t1.join()
t2.join()
t3.join()
print balance
結果 :
[/data/web/test_python]$ python multhread_threading.py
0
[/data/web/test_python]$ python multhread_threading.py
61
[/data/web/test_python]$ python multhread_threading.py
0
[/data/web/test_python]$ python multhread_threading.py
24
上面的例子引出了多線程編程的最常見問題:數據共享。當多個線程都修改某一個共享數據的時候,需要進行同步控制。
線程同步能夠保證多個線程安全訪問競爭資源,最簡單的同步機制是引入互斥鎖。互斥鎖為資源引入一個狀態:鎖定/非鎖定。某個線程要更改共享數據時,先將其鎖定,此時資源的狀態為「鎖定」,其他線程不能更改;直到該線程釋放資源,將資源的狀態變成「非鎖定」,其他的線程才能再次鎖定該資源。互斥鎖保證了每次只有一個線程進行寫入操作,從而保證了多線程情況下數據的正確性。
threading模塊中定義了Lock類,可以方便的處理鎖定:
#創建鎖mutex = threading.Lock()
#鎖定mutex.acquire([timeout])
#釋放mutex.release()
其中,鎖定方法acquire可以有一個超時時間的可選參數timeout。如果設定了timeout,則在超時後通過返回值可以判斷是否得到了鎖,從而可以進行一些其他的處理。
使用互斥鎖實現上面的例子的代碼如下:
balance = 0
muxlock = threading.Lock()
def change_it(n):
# 獲取鎖,確保只有一個線程操作這個數
muxlock.acquire()
global balance
balance = balance + n
balance = balance - n
# 釋放鎖,給其他被阻塞的線程繼續操作
muxlock.release()
def run_thread(n):
for i in range(10000):
change_it(n)
加鎖後的結果,就能確保數據正確:
[/data/web/test_python]$ python multhread_threading.py
0
[/data/web/test_python]$ python multhread_threading.py
0
[/data/web/test_python]$ python multhread_threading.py
0
[/data/web/test_python]$ python multhread_threading.py
0
7. Python多線程之threading之Lock對象
要介紹Python的 threading 模塊中的 Lock 對象前, 首先應該了解以下兩個概念:
1.基本概念 : 指某個函數/函數庫在多線程環境中被調用時, 能夠正確地處理多個線程之間的 共享變數 , 使程序功能正常完成. 多個線程訪問同一個對象時, 如果不用考慮這些線程在運行時環境下的調度和交替執行, 也不需要進行額外的同步, 或者在調用方進行任何其他操作,調用這個對象的行為都可以獲得正確的結果, 那麼這個對象就是線程安全的. 或者說: 一個類或者程序所提供的介面對於線程來說是 原子操作 或者多個線程之間的切換不會導致該介面的執行結果存在二義性, 也就是說我們不用考慮同步的問題.
2.示例 : 比如有間銀行只有1000元, 而兩個人同時提領1000元時,就有可能拿到總計2000元的金額. 為了避免這個問題, 該間銀行提款時應該使用 互斥鎖 , 即意味著對同一個資源處理時, 前一個提領交易完成後才處理下一筆交易.
3.線程安全意義 :
4.是否線程安全 :
5.資源競爭 : 即多個線程對同一個資源的改寫時, 存在的一種競爭. 如果僅僅是讀操作, 則不存在資源競爭的情況.
1.基本概念 : 因為存在上述所說的 線程安全與資源競爭 的情況, 所以引入了 線程鎖 . 即通過鎖來進行資源請求的限制, 以保證同步執行,避免資源被污染或預期結果不符. 線程鎖存在兩種狀態: 鎖定(locked)和非鎖定(unlocked).
2.基本方法 :
3.使用示例 :
上述示例如果在不加鎖的情況下, 將會出現列印順序混亂的情況, 不過最終結果都是正確的, 因為即使線程交替執行, 但最終的結果都是一致.
8. 怎麼樣給python文件加密
簡單模式:
from hashlib import md5
def md5_file(name):
m = md5()
a_file = open(name, 'rb') #需要使用二進制格式讀取文件內容
m.update(a_file.read())
a_file.close()
return m.hexdigest()
if __main__ == '__init__':
print md5_file('d:/test.txt')
大文件速度更快一點的方式
#!/usr/bin/python
#encoding=utf-8
import io
import sys
import hashlib
import string
def printUsage():
print ('''''Usage: [python] pymd5sum.py ''')
def main():
if(sys.argv.__len__()==2):
#print(sys.argv[1])
m = hashlib.md5()
file = io.FileIO(sys.argv[1],'r')
bytes = file.read(1024)
while(bytes != b''):
m.update(bytes)
bytes = file.read(1024)
file.close()
#md5value = ""
md5value = m.hexdigest()
print(md5value+"\t"+sys.argv[1])
#dest = io.FileIO(sys.argv[1]+".CHECKSUM.md5",'w')
#dest.write(md5value)
#dest.close()
else:
printUsage()
main()