2013-06-13 115 views
5

Tôi chạy đoạn mã sau bằng Python 2.7.5. hệ điều hành Windows:Thời gian sửa đổi tệp không bằng nhau sau khi gọi shutil.copystat (tệp1, tệp2) trong Windows

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?! 

Tôi hy vọng cả hai timestamps (= phao) là bằng nhau (như cơ quan đại diện chuỗi của họ đề nghị), vậy tại sao không t1 == t2 đánh giá để False?

Ngoài ra, tôi không thể tạo lại hành vi này với mã ít hơn, tức là không so sánh dấu thời gian được truy xuất qua os.lstat từ hai các tệp khác nhau. Tôi có cảm giác, tôi thiếu cái gì tầm thường ở đây ...


Edit: Sau khi thử nghiệm thêm nữa tôi nhận thấy, mà nó in True một lần trong một thời gian, nhưng không thường xuyên nhiều hơn một lần mỗi 10 chạy.


Sửa 2: Theo đề nghị của larsmans:

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

Điều này đặt ra hai câu hỏi mới:

  1. Tại sao các timestamps không bằng sau khi gọi shutil.copystat?
  2. print vòng nổi theo mặc định ?!
+0

Không thể sao chép trên Debian Linux. Hãy thử 'in ("%. 7f "% t1)' và '(t1 - t2) <1e-4' để xem" bản in nhỏ "có khác không. –

+0

Để xem lý do tại sao vòng in nổi theo mặc định, hãy thử: 'x = 10.1 (dòng mới) in ("% .20f "% x)'. Điều này sẽ in một cái gì đó khác hơn bạn nghĩ. Điều này là bình thường vì các giá trị dấu phẩy động không thể đại diện cho tất cả các giá trị phân số chính xác. Tôi không có ý kiến ​​về vấn đề shutil mặc dù. –

+0

Tôi biết về biểu diễn nhị phân, nhưng ở đây trường hợp khác nhau: Chúng ta có float với giá trị '10.099999' và nó in '10.1' mặc dù chúng tôi không chỉ định định dạng như'% .2f' - vì vậy dường như là làm tròn tiềm ẩn có hiệu lực, mà tôi không biết và rằng tôi chưa bao giờ quan sát trước đây ... –

Trả lời

5

Vấn đề là với chuyển đổi giữa các định dạng khác nhau trong copystat gọi. Điều này là do Windows lưu trữ thời gian tệp theo định dạng thập phân cố định, trong khi Python lưu trữ chúng theo định dạng nhị phân dấu phẩy động. Vì vậy, mỗi lần có một chuyển đổi giữa hai định dạng, một số độ chính xác bị mất.Trong các cuộc gọi copystat:

  1. Chuyển đổi định dạng Windows sang định dạng dấu phẩy động của Python. Một số độ chính xác bị mất.
  2. os.utime được gọi để cập nhật thời gian tệp. điều này chuyển đổi nó trở lại định dạng Windows. Một số độ chính xác bị mất một lần nữa và thời gian tệp không nhất thiết giống với tệp đầu tiên.

Khi bạn gọi os.lstat chính mình, một chuyển đổi không chính xác thứ ba được thực hiện. Do những chuyển đổi này, thời gian tệp không giống nhau.

Các documentation for os.utime đề cập đến điều này:

Lưu ý rằng thời gian chính xác mà bạn đặt ở đây có thể không được trả lại bởi một stat tiếp theo() gọi, tùy thuộc vào độ phân giải mà hệ điều hành của bạn hồ sơ truy cập và sửa đổi lần


về câu hỏi thứ hai của bạn (tại sao print xuất hiện để hiển thị các giá trị tương tự cho cả hai): Chuyển đổi một giá trị dấu chấm động với một chuỗi với str(f) hoặc print f sẽ làm tròn giá trị. Để có được một giá trị được đảm bảo là duy nhất cho các giá trị dấu phẩy động khác nhau, hãy sử dụng print repr(f) để thay thế.

-1

Thử in chênh lệch thời gian trong dấu chấm động: print float.hex(t1 - t2)

kết quả:

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

2cents tôi đoán: sự thay đổi trong sản lượng xuất phát từ floating point đại diện thiên vị và làm tròn lỗi. Dù sao, bạn nên luôn luôn sử dụng một giá trị epsilon khi so sánh hai phao.

EDIT: kiểm tra điều này Python bug.

Đây là giới hạn hệ thống. Hệ thống tệp cơ bản hỗ trợ độ phân giải nano giây cho các tệp tem và chỉ số (2) cũng hỗ trợ báo cáo chúng. Tuy nhiên, utimes (2) chỉ hỗ trợ độ phân giải micro giây khi đặt chúng.

Bạn phải sử dụng độ phân giải micro giây ở mức tốt nhất khi so sánh hai phao.

+1

vâng, điều gây rắc rối hơn là t1 lớn hơn t2, trong khi ngược lại (text2 gần đây hơn text1) – lucasg

+0

Lỗi đó báo cáo dành cho hệ thống Linux. Việc cài đặt Windows của Python không sử dụng 'utimes', vì vậy không có giới hạn micro giây như vậy. – interjay

+0

GetFileTime (http://msdn.microsoft.com/en-us/library/windows/desktop/ms724320 (v = vs.85) .aspx) có độ phân giải 10 milisecond, vì vậy tôi cho rằng shutil trên Windows không thể làm tốt hơn. (Tôi đã nhìn vào mã Python và lstat gọi winapi GetFileAttributesExW ) – lucasg

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

Sử dụng vòng() cho t1 và t2