2015-05-15 48 views
0

我很難理解第二個'打開'功能在這裏做什麼。瞭解多個python'打開'文件功能

所以,在第一個'開放'部分,我們基本上說過out = open(save_as_file, 'wb+'),對吧? (對於使用'開放'仍然是新的)。我們稍後寫入它,然後'打開'自動關閉'out'文件。我得到的那部分 - 我們將這個響應對象從Requests中作爲二進制文件寫入指定的save_as_file位置,直到我們點擊第81920個字符,即我們的緩衝區#。

第二個'開放'發生了什麼?按照與上面相同的方式分解它,這幾乎是fp = open(save_as_file, 'r'),對吧?這是什麼使得fp早已被分配了請求響應對象?我們只是打開save_as_file來使用它來閱讀,但不能讀取或提取任何東西,所以我沒有看到它的原因。如果有人能用英文解釋發生了什麼,以及第二個「開放」部分的目的,那將非常感激。

(不用擔心在年底load_from_file功能,這僅僅是類下的另一個功能)

def load_from_url(self, url, save_as_file=None): 

    fp = requests.get(url, stream=True, 
         headers={'Accept-Encoding': None}).raw 

    if save_as_file is None: 
     return self.load_from_file(fp) 

    else: 
     with open(save_as_file, 'wb+') as out: 
      while True: 
       buffer = fp.read(81920) 
       if not buffer: 
        break 
       out.write(buffer) 
     with open(save_as_file) as fp: 
      return self.load_from_file(fp) 
+0

HTTPS://www.p ython.org/dev/peps/pep-0343/ – Shashank

回答

1

你是對的,第二個with語句打開文件供閱讀。

什麼情況是這樣的:

  1. 負載從URL的響應
  2. 如果save_as_file是無:在響應
    1. 呼叫load_from_file並返回結果
  3. 否則:
    1. 將回復的內容存儲到save_as_file
    2. 上的文件的內容
    3. 呼叫load_from_file並返回結果

所以essentialy,如果save_as_file設置它存儲的響應主體在一個文件,處理它,然後返回處理結果。否則它只處理響應主體並返回結果。

它在這裏實現的方式可能是因爲load_from_file需要一個類似文件的對象,並且程序員看到的最簡單的方法就是讀取文件。

它可以通過保持在存儲器中的響應體和使用Python 3的io模塊或Python 2的StringIO提供一種使用響應主體從存儲器,從而避免需要再次讀取文件中的類文件對象來完成。

fp被重新分配到第二個with語句中,其方式與其他任何變量相同,如果您爲其分配另一個值。

1

我用下面的代碼試圖模仿你的情況:

fp = open("/Users/example1.py",'wb+') 

print "first fp",fp 

with open("/Users/example2.py") as fp: 
    print "second fp",fp 

的輸出是:

first fp <open file '/Users/example1.py', mode 'wb+' at 0x10b200390> 
second fp <open file '/Users/example2.py', mode 'r' at 0x10b200420> 

所以第二fp是內部一個局部變量塊。

您的代碼似乎要首先從URL中讀取數據,並將其寫入save_as_file,然後再從save_as_file讀取數據,並做一些與load_from_file,比如驗證內容。

+0

也是一個很好的答案 - 只是喜歡@Raniz向我解釋的方式,就像我5歲時一樣。 – SpicyClubSauce

+0

如果你覺得有用,請考慮一個upvote :)我的經驗是添加斷點會幫助你理解。 – Wingzero

+0

完成。謝啦! – SpicyClubSauce

2

我是你所指的code的原始author;我同意這有點不清楚。

如果我們點擊else聲明中的特定代碼,這意味着我們要將最初從calling the URL獲得的數據保存到文件中。這裏,fp實際上是來自URL調用的響應文本。

如果從命令行運行,我們會通過--cpi-file=foobar.txt,並且該文件實際上還不存在,我們將打到該else語句;它作爲here提到的目標文件。如果您沒有通過--cpi-file=foobar.txt,那麼程序將而不是寫入文件,它將直接通過load_from_file直接讀取響應數據(從fp)。我們將從URL(fp)中獲取數據,並將該數據寫入目標文件(save_as_file)。然後,如果該文件不存在但我們確實通過它在命令行中,我們將從URL(fp)中獲取數據,並將該數據寫入目標文件(save_as_file)。它現在存在供我們參考(它將在您的文件系統上),如果我們想在此腳本中再次使用它。

然後,我們將再次打開該確切文件,並呼叫load_from_file實際讀取和解析我們最初從響應中獲得的數據(fp)。

現在 - 如果我們運行這個腳本兩次,則--cpi-file=foobar.txtfoobar.txt都不存在,腳本第一次運行時,它將創建文件並保存CPI數據。腳本第二次運行時,它實際上會避免再次調用CPI​​ URL重新下載數據,並且僅去straight to parsing the CPI data from the file

load_from_file是有點誤導的名字,這也許應該是load_from_stream,因爲它可以從our api call或從文件中讀取響應數據。

希望這是有道理的。在newcoder.io的下一個版本中,我一定會清除這個語言的代碼&。

0

這裏是一段代碼描述它:

  1. __with__提供一個塊時存在
  2. 可以處理塊內發生
  3. 也可以執行代碼時例外「清理」進入

class MyClass(object): 

    def __enter__(self): 
     print("entering the myclass %s") 
     return self 

    def __exit__(self, type, value, traceback): 
     print("Exitinstance %s" %(id(self))) 
     print("error type {0}".format(type)) 
     print("error value {0}".format(value)) 
     print("error traceback {0}".format(traceback)) 
     print("exiting the myclass") 

    def sayhi(self): 
     print("Sayhi instance %s" %(id(self))) 

with MyClass() as cc: 
    cc.sayhi() 


print("after the block ends") 
+0

您可以將代碼粘貼到http://www.pythontutor.com並查看它是如何工作的 – Stryker