2013-08-06 99 views
0

我使用Python中生成功能練習,所以我定義的功能如下:使用發電機功能蟒蛇

def MySQL_product(): 
    #Establish connection to database 
    try: 
     connection = msql.connect(host = 'localhost', user = 'max', passwd = 'password', db = 'schools') 
    except: 
     pass 

    #Iterate through each product and insert them in database 
    with connection: 
     cursor = connection.cursor() 
     cursor.execute("SELECT name, age, gender, school 
        WHERE GroupId = 'student' AND Exchange = 'foreign'") 
     for product in cursor.fetchall(): 
      yield product 

def main(): 
    for column in range (0, number_of_schools): 
     for product in MySQL_product(): 
      print product 

然而,當我運行此代碼,我看到的是一個輸出generator object at ...我想打印在數據庫中找到的內容。另外,MySQL_product()中的print語句都沒有執行。生成器的要點是,不要返回數據庫中所有行的列表,而應該逐個返回它。然後我想訪問/打印這些項目。我能做些什麼來解決這個問題?

回答

3

如果你正在做一個cursor.fetchall(),這意味着你將從SQL服務器得到的每個結果拷貝到python的內存中。所以在這種情況下 - 發電機不會爲您提供任何幫助。

如果您改爲使用cursor.fetchmany()或cursor.fetchone(),您將看到的唯一好處是Python方面的內存消耗,因爲您一次只能處理「一些」或「一個」結果。在SQL方面,服務器仍然會緩存結果集(燒燬SQL服務器上的寶貴資源)

但是,最終 - 如果您以塊處理結果 - 因爲您將處於以下循環中:

while there_are_more_results: 
    results = cursor.fetchmany(10) 
    for result in results: 
     do_something(result) 

擁有一個生成器將不會提供任何真正的優勢,因爲當你從mysql獲得更多結果時,你將不得不阻止。

但是,要回答你的問題

你想做的事,使你在工作的代碼是什麼:

def main(): 
    for column in range (0, number_of_schools): 
     for student in MySQL_product(): 
      print student 

發電機是真正有用的,當你異步做的事情 - 基本上如果發電機還沒有準備好 - 你只是略過它,讓其他事情工作。

+0

所以做我改變'使用fetchall()''中MySQL_product()''到fetchone()'當我執行你的'main'? –

+0

一次獲取一個結果會非常慢,最佳大小取決於您的mysql服務器如何調優。嘗試256作爲一個起點。 – synthesizerpatel

+0

我不確定我是否遵循你的意思,你可以看看編輯過的問題嗎?如果我明白你說的話,發電機不能在這個問題中有效地使用? –

0

我的第一個答案是不正確的,其他人已經給出了最好的解決方案,所以我會陳述替代性和潛在的使用情況。如果您需要遍歷發電機兩個項目的時間,或以任何其他自定義方式,next方法是有用的。

def gen(): 
    for i in range(20): 
     yield i 

for i in gen(): 
    print "Center", str(i).center(10) 

a = gen()  
for i in range(10): 
    left = str(a.next()).ljust(10) 
    right = str(a.next()).rjust(10) 
+1

打印students.next()將只打印一個結果。你必須遍歷生成器。 – synthesizerpatel

+0

是的,我正要編輯我的答案,因爲我意識到這一點。 –

2

是的,這是一個生成的行爲 - 它總是返回一個迭代器,你可以接着用例如使用for聲明。你可能想你main()功能更改爲類似這樣:

def main(): 
    for column in range (0, number_of_schools): 
     for student in MySQL_product(): 
      print student 

也有可能獲得通過與next()功能的迭代器產生下一個結果,但總的來說,你應該更喜歡直接與for item in iterator: # ...迭代(因爲你的代碼會更容易閱讀,並且在你做一些事情時,比如從一個生成器函數切換回一個返回一個列表的常規代碼時,它的脆弱程度會更低。

+0

我的'MySQL_product()'函數怎麼樣,我更改'fetchall()'? –

+0

@MaxKim不知道;我沒有看到你的'MySQL_product()'函數......但是@synthesizerpatel似乎有你的覆蓋。 –