2013-06-13 71 views
5

我使用Python 2.7.5運行以下代碼。在Windows下:在Windows下調用shutil.copystat(file1,file2)後文件修改時間不相等

import os, shutil, stat, time 

with open('test.txt', 'w') as f: pass # create an arbitrary file 
shutil.copy('test.txt', 'test2.txt') # copy it 
shutil.copystat('test.txt', 'test2.txt') # copy its stats, too 

t1 = os.lstat('test.txt').st_mtime # get the time of last modification for both files 
t2 = os.lstat('test2.txt').st_mtime 

print t1 # prints something like: 1371123658.54 
print t2 # prints the same string, as expected: 1371123658.54 
print t1 == t2 # prints False! Why?! 

我以爲這兩個時間戳(=浮動)相等(因爲它們的字符串表示建議),所以爲什麼t1 == t2評估爲False

此外,我無法用較少的代碼重現此行爲,即無需比較通過os.lstat從兩個不同的文件中檢索到的時間戳。我有一種感覺,我失去了一些東西小事這裏...


編輯:進一步測試我發現後,它可以打印 True過一段時間,但不超過一次,每10運行。


編輯2:正如larsmans建議:

print ("%.7f" % t1) # prints e.g. 1371126279.1365688 
print ("%.7f" % t2) # prints e.g. 1371126279.1365681 

這就提出了兩個新問題:

  1. 爲什麼時間戳沒有要求shutil.copystat後平等的嗎?
  2. print輪默認浮動?!
+0

無法在Debian Linux上重現。嘗試'print(「%。7f」%t1)'和'(t1-t2)<1e-4'來查看「小字體」是否不同。 –

+0

要了解爲什麼默認情況下打印循環是浮動的,試試這個:'x = 10.1(newline)print(「%.20f」%x)'。這會打印出你認爲不同的東西。這是正常的,因爲浮點值不能完全表示所有小數值。儘管如此,我並不知道這個問題。 –

+0

我知道二進制表示,但這裏的情況是不同的:我們有一個值爲「10.099999」的浮點數,雖然我們沒有指定諸如「%.2f」之類的格式,但它打印的是'10.1' - 所以似乎有一個隱含的四捨五入效果,我不知道,我從來沒有觀察過...... –

回答

5

的問題是與copystat呼叫期間不同格式之間的轉換。這是因爲Windows將文件時間存儲爲定點十進制格式,而Python將它們存儲爲浮點二進制格式。所以每次在兩種格式之間進行轉換時,都會失去一些準確性。在copystat電話:

  1. os.stat調用轉換的Windows格式Python的浮點格式。一些準確性丟失了。
  2. os.utime被調用來更新文件時間。這會將其轉換回Windows格式。一些準確性再次丟失,文件時間不一定與第一個文件相同。

當您自己撥打os.lstat時,會執行第三次不準確的轉換。由於這些轉換,文件時間並不完全相同。

documentation for os.utime提到了這一點:

請注意,您在此處設置的確切時間可能不會被後續的stat()調用返回,取決於分辨率與您的操作系統的記錄訪問和修改時間


關於你提到的第二個問題(爲什麼print似乎顯示了兩個相同的值):一個浮點值轉換爲字符串str(f)print f將輪值。要獲得保證對不同浮點值唯一的值,請改用print repr(f)

-1

嘗試打印在浮點時差:print float.hex(t1 - t2)

結果:

0x1.0000000000000p-22 
0x1.8000000000000p-21 
0x0.0p+0 
0x1.0000000000000p-20 

我的2分錢小費的猜測:在輸出的變化來自於浮點表示偏差和舍入誤差。無論如何,當比較兩個浮動時,您應該始終使用一個epsilon值。

編輯:檢查這個Python bug

這是一個系統限制。底層文件系統支持 納秒分辨率的文件標記,並且stat(2)也支持 報告它們。但是,設置它們時,utimes(2)僅支持微秒級的 分辨率。

當比較兩個浮點數時,您最好使用微秒分辨率。

+1

是的,更令人不安的是,t1大於t2,而它應該是相反的(text2比text1更新) – lucasg

+0

那個bug報告是針對Linux系統的。 Python的Windows實現不使用'utimes',所以不存在這樣的微秒限制。 – interjay

+0

GetFileTime(http://msdn.microsoft.com/en-us/library/windows/desktop/ms724320(v = vs.85).aspx)具有10毫秒的分辨率,因此我認爲Windows上的shutil無法做得更好。 (我看了Python代碼和lstat調用winapi GetFileAttributesExW ) – lucasg

0
from decimal import * 
print Decimal(t1) 
print Decimal(t2) 

使用輪()爲t1和t2

相關問題