ฉันมีสคริปต์ที่ความต้องการที่จะทำบางสิ่งที่อยู่บนพื้นฐานของการสร้างไฟล์และการปรับเปลี่ยนวัน แต่มีการทำงานบนลินุกซ์และวินโดวส์
วิธีข้ามแพลตฟอร์มที่ดีที่สุดในการสร้างและแก้ไขไฟล์date/times
ในPythonคืออะไร
ฉันมีสคริปต์ที่ความต้องการที่จะทำบางสิ่งที่อยู่บนพื้นฐานของการสร้างไฟล์และการปรับเปลี่ยนวัน แต่มีการทำงานบนลินุกซ์และวินโดวส์
วิธีข้ามแพลตฟอร์มที่ดีที่สุดในการสร้างและแก้ไขไฟล์date/times
ในPythonคืออะไร
คำตอบ:
การได้รับวันที่แก้ไขบางอย่างในแบบข้ามแพลตฟอร์มเป็นเรื่องง่ายเพียงแค่โทรแล้วคุณจะได้รับการประทับเวลา Unix เมื่อไฟล์ที่ถูกแก้ไขครั้งล่าสุดos.path.getmtime(path)
path
การได้รับวันที่สร้างไฟล์ในทางกลับกันเป็นเรื่องยุ่งและขึ้นอยู่กับแพลตฟอร์มซึ่งแตกต่างกันระหว่างสามระบบปฏิบัติการขนาดใหญ่:
ctime
(จัดทำเป็นเอกสารที่https://msdn.microsoft.com/en-us/library/14h5k7ff.aspx ) จัดเก็บวันที่สร้าง คุณสามารถเข้าถึงนี้ในหลามผ่านos.path.getctime()
หรือแอตทริบิวต์ของผลมาจากการเรียกร้องให้มี.st_ctime
os.stat()
นี้จะไม่ทำงานบนระบบปฏิบัติการยูนิกซ์ที่ctime
จะเป็นครั้งสุดท้ายว่าแอตทริบิวต์ของไฟล์หรือเนื้อหาที่มีการเปลี่ยนแปลง.st_birthtime
os.stat()
บนLinuxนี่เป็นไปไม่ได้อย่างน้อยในตอนนี้โดยไม่ต้องเขียน C extension สำหรับ Python แม้ว่าบางระบบไฟล์ที่ใช้กันทั่วไปกับ Linux ทำร้านค้าวันที่สร้าง (ตัวอย่างเช่นext4
เก็บไว้ในst_crtime
), ลินุกซ์เคอร์เนลข้อเสนอวิธีการเข้าถึงพวกเขา ; โดยเฉพาะอย่างยิ่ง structs มันกลับมาจากstat()
การโทรใน C เป็นของเคอร์เนลรุ่นล่าสุดไม่ได้มีสาขาวันที่สร้างใด ๆ นอกจากนี้คุณยังจะเห็นว่าตัวระบุst_crtime
ไม่ได้ในขณะนี้มีที่ใดก็ได้ในแหล่งหลาม อย่างน้อยถ้าคุณเปิดอยู่ext4
ข้อมูลจะถูกแนบกับ inodes ในระบบไฟล์ แต่ไม่มีวิธีที่สะดวกในการเข้าถึง
สิ่งที่ดีที่สุดถัดไปบน Linux คือการเข้าถึงไฟล์mtime
โดยos.path.getmtime()
ใช้.st_mtime
คุณสมบัติหรือos.stat()
ผลลัพธ์ นี่จะทำให้คุณได้รับการแก้ไขเนื้อหาของไฟล์ครั้งล่าสุดซึ่งอาจเพียงพอสำหรับการใช้งานบางกรณี
การรวมทั้งหมดเข้าด้วยกันโค้ดข้ามแพลตฟอร์มควรมีลักษณะเช่นนี้ ...
import os
import platform
def creation_date(path_to_file):
"""
Try to get the date that a file was created, falling back to when it was
last modified if that isn't possible.
See http://stackoverflow.com/a/39501288/1709587 for explanation.
"""
if platform.system() == 'Windows':
return os.path.getctime(path_to_file)
else:
stat = os.stat(path_to_file)
try:
return stat.st_birthtime
except AttributeError:
# We're probably on Linux. No easy way to get creation dates here,
# so we'll settle for when its content was last modified.
return stat.st_mtime
ext4
ไดรฟ์ภายใต้ Linux และฉันต้องการเรียนรู้ว่าเกิดอะไรขึ้นเมื่อ Linux อ่านไฟล์ที่เขียนโดย Windows หรือ vica ในทางกลับกันเนื่องจากพวกเขาใช้st_ctime
แตกต่างกัน
"w"
มันไม่ได้แทนที่มันเพียงแค่เปิดไฟล์ที่มีอยู่และตัดทอน แม้ว่าเนื้อหาของไฟล์จะไม่เกี่ยวข้องอย่างสมบูรณ์กับสิ่งที่มีอยู่ในการสร้างคุณยังคงได้รับการบอกว่าไฟล์นั้น "ถูกสร้าง" ก่อนเวอร์ชั่นปัจจุบัน ในทางกลับกันบรรณาธิการที่ใช้การแทนที่อะตอมมิกในการบันทึก (ไฟล์ต้นฉบับจะถูกแทนที่ด้วยไฟล์ชั่วคราว work-in-คืบหน้าใหม่) จะแสดงวันที่สร้างล่าสุดมากกว่าแม้ว่าคุณเพิ่งลบหนึ่งอักขระ ใช้เวลาแก้ไขไม่ด้วงสำหรับเวลาสร้าง
stat.st_ctime
มีความเกี่ยวข้องมากขึ้นเนื่องจากในหลายกรณีเวลาของการเปลี่ยนแปลงข้อมูลเมตาครั้งล่าสุดอาจเป็นเวลาการสร้าง (อย่างน้อยctime
ก็ใกล้เคียงกับเวลาการสร้างจริงมากกว่าmtime
) stat = os.stat(path_to_file); try: return stat.st_birthtime; except AttributeError: return stat.st_ctime
ดังนั้นคุณก็สามารถเปลี่ยนข้อมูลโค้ดของคุณโดย คุณคิดอย่างไร? ไชโย
ctime
ควรจะเท่ากับหรือภายหลังกว่าmtime
เพราะmtime
การเปลี่ยนแปลงที่ทำให้เกิดctime
เปลี่ยนแปลง (เพราะmtime
ตัวเองจะถือว่าเป็น "เมตาดาต้า") ดูstackoverflow.com/a/39521489/1709587ที่ฉันให้รหัสตัวอย่างเพื่อแสดงสิ่งนี้
คุณมีทางเลือกสองทาง สำหรับหนึ่งคุณสามารถใช้os.path.getmtime
และos.path.getctime
ฟังก์ชั่น:
import os.path, time
print("last modified: %s" % time.ctime(os.path.getmtime(file)))
print("created: %s" % time.ctime(os.path.getctime(file)))
ตัวเลือกอื่นของคุณคือใช้os.stat
:
import os, time
(mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime) = os.stat(file)
print("last modified: %s" % time.ctime(mtime))
หมายเหตุ : ctime()
ไม่ได้อ้างถึงเวลาการสร้างบนระบบ * nix แต่เป็นครั้งสุดท้ายที่ข้อมูล inode เปลี่ยนไป (ขอบคุณ kojiro ที่ทำให้ข้อเท็จจริงนั้นชัดเจนยิ่งขึ้นในความคิดเห็นโดยให้ลิงก์ไปยังโพสต์บล็อกที่น่าสนใจ)
ctime
ได้รับการปรับปรุงเมื่อmtime
ไม่ (ตั้งแต่mtime
เป็น "เมตาดาต้า") และเพื่อให้ctime
เป็นปกติมักจะเท่ากับหรือไปข้างหน้าของ mtime
ปฏิบัติctime
เหมือนเวลา "สร้าง" จึงไม่สมเหตุสมผลเลย -1!
Last modified: Fri Jan 31 11:08:13 2020
และ Created: Fri Jan 31 11:08:13 2020
บน Ubuntu Ubuntu 16.04!
time.ctime(os.path.getmtime(file))
คืนค่าสตริง 2 ประเภทขึ้นอยู่กับว่าไฟล์นั้นถูกแก้ไขโดยระบบหรือโดยผู้ใช้ หากมีการแก้ไขโดยระบบสตริงจะมี 2 ช่องว่างระหว่างเดือนและวัน ฉันไม่รู้ว่าทำไม
ฟังก์ชั่นที่ดีที่สุดที่จะใช้สำหรับเรื่องนี้คือos.path.getmtime () os.stat(filename).st_mtime
ภายในเพียงแค่นี้การใช้งาน
โมดูล datetime เป็น timestamps ที่จัดการได้ดีที่สุดดังนั้นคุณสามารถรับวันที่แก้ไขเป็นdatetime
วัตถุเช่นนี้:
import os
import datetime
def modification_date(filename):
t = os.path.getmtime(filename)
return datetime.datetime.fromtimestamp(t)
ตัวอย่างการใช้งาน:
>>> d = modification_date('/var/log/syslog')
>>> print d
2009-10-06 10:50:01
>>> print repr(d)
datetime.datetime(2009, 10, 6, 10, 50, 1)
getmtime
เป็นสิ่งที่ใกล้ที่สุดที่มีอยู่ใน Unix (ซึ่งไม่สามารถสร้างวันที่สร้างได้) แต่ไม่ใช่ฟังก์ชั่นที่ดีที่สุดในการใช้งานบน Windows ซึ่งctime
เป็นช่วงเวลาในการสร้าง
os.stat https://docs.python.org/2/library/stat.html#module-stat
แก้ไข: ในรหัสที่ใหม่กว่าคุณควรใช้os.path.getmtime () (ขอบคุณ Christian Oudard)
แต่โปรดทราบว่ามันคืนค่าทศนิยมของ time_t ด้วยเศษเสี้ยววินาที (หากระบบปฏิบัติการของคุณรองรับ)
os.path.getmtime()
ได้รับมาตั้งแต่ Python 1.5.2 (ดูเอกสารเก่า ) ที่ปล่อยออกมาก่อนที่ฉันจะสูญเสียฟันน้ำนมของฉันเกือบสิบปีก่อนที่คุณจะเขียนคำตอบดั้งเดิมนี้
มีสองวิธีในการรับเวลา mod, os.path.getmtime () หรือ os.stat () แต่ ctime ไม่น่าเชื่อถือข้ามแพลตฟอร์ม (ดูด้านล่าง)
getmtime ( path )
คืนค่าเวลาของการแก้ไข path ครั้งล่าสุด ค่าที่ส่งคืนคือตัวเลขที่ระบุจำนวนวินาทีตั้งแต่ยุค (ดูโมดูลเวลา) เพิ่ม os.error หากไฟล์ไม่มีอยู่หรือไม่สามารถเข้าถึงได้ ใหม่ในรุ่น 1.5.2 เปลี่ยนเป็นเวอร์ชั่น 2.3: หาก os.stat_float_times () ส่งคืนค่า True ผลลัพธ์จะเป็นเลขทศนิยม
stat ( เส้นทาง )
ทำการเรียกระบบ stat () บนเส้นทางที่กำหนด ค่าส่งคืนเป็นวัตถุที่มีคุณลักษณะที่สอดคล้องกับสมาชิกของโครงสร้าง stat ได้แก่ : st_mode (บิตป้องกัน), st_ino (หมายเลขไอโหนด), st_dev (อุปกรณ์), st_nlink (จำนวนฮาร์ดลิงก์), st_uid (ID ผู้ใช้ของเจ้าของ ), st_gid (ID กลุ่มของเจ้าของ), st_size (ขนาดของไฟล์, เป็นไบต์), st_atime (เวลาที่เข้าถึงล่าสุด), st_mtime (เวลาของการแก้ไขเนื้อหาล่าสุด), st_ctime (ขึ้นอยู่กับแพลตฟอร์ม; เวลาของการเปลี่ยนแปลงข้อมูลเมตาล่าสุด บน Unix หรือเวลาที่สร้างบน Windows) :
>>> import os
>>> statinfo = os.stat('somefile.txt')
>>> statinfo
(33188, 422511L, 769L, 1, 1032, 100, 926L, 1105022698,1105022732, 1105022732)
>>> statinfo.st_size
926L
>>>
ในตัวอย่างข้างต้นคุณจะใช้ statinfo.st_mtime หรือ statinfo.st_ctime เพื่อรับ mtime และ ctime ตามลำดับ
ใน Python 3.4 และสูงกว่าคุณสามารถใช้ส่วนต่อประสานโมดูล pathlibเชิงวัตถุซึ่งรวมถึง wrappers สำหรับโมดูล OS ส่วนใหญ่ นี่คือตัวอย่างของการรับสถิติไฟล์
>>> import pathlib
>>> fname = pathlib.Path('test.py')
>>> assert fname.exists(), f'No such file: {fname}' # check that the file exists
>>> print(fname.stat())
os.stat_result(st_mode=33206, st_ino=5066549581564298, st_dev=573948050, st_nlink=1, st_uid=0, st_gid=0, st_size=413, st_atime=1523480272, st_mtime=1539787740, st_ctime=1523480272)
สำหรับข้อมูลเพิ่มเติมเกี่ยวกับสิ่งที่os.stat_result
มีให้ดูที่เอกสาร สำหรับเวลาการแก้ไขที่คุณต้องการfname.stat().st_mtime
:
>>> import datetime
>>> mtime = datetime.datetime.fromtimestamp(fname.stat().st_mtime)
>>> print(mtime)
datetime.datetime(2018, 10, 17, 10, 49, 0, 249980)
หากคุณต้องการเวลาสร้างบน Windows หรือการเปลี่ยนแปลงข้อมูลเมตาล่าสุดใน Unix คุณจะใช้fname.stat().st_ctime
:
>>> ctime = datetime.datetime.fromtimestamp(fname.stat().st_ctime)
>>> print(ctime)
datetime.datetime(2018, 4, 11, 16, 57, 52, 151953)
บทความนี้มีข้อมูลที่เป็นประโยชน์มากขึ้นและตัวอย่างสำหรับโมดูล pathlib
os.stat
ส่งคืน tuple ที่มีชื่อด้วยst_mtime
และst_ctime
คุณลักษณะ เวลาแก้ไขอยู่st_mtime
บนทั้งสองแพลตฟอร์ม น่าเสียดายที่บน Windows ctime
หมายถึง "เวลาสร้าง" ในขณะที่ POSIX หมายถึง "เปลี่ยนเวลา" ฉันไม่ทราบว่าจะใช้วิธีใดในการสร้างเวลาบนแพลตฟอร์ม POSIX
dir(..)
ใช้ เช่นdir(os.stat(os.listdir('.')[0]))
import os, time, datetime
file = "somefile.txt"
print(file)
print("Modified")
print(os.stat(file)[-2])
print(os.stat(file).st_mtime)
print(os.path.getmtime(file))
print()
print("Created")
print(os.stat(file)[-1])
print(os.stat(file).st_ctime)
print(os.path.getctime(file))
print()
modified = os.path.getmtime(file)
print("Date modified: "+time.ctime(modified))
print("Date modified:",datetime.datetime.fromtimestamp(modified))
year,month,day,hour,minute,second=time.localtime(modified)[:-3]
print("Date modified: %02d/%02d/%d %02d:%02d:%02d"%(day,month,year,hour,minute,second))
print()
created = os.path.getctime(file)
print("Date created: "+time.ctime(created))
print("Date created:",datetime.datetime.fromtimestamp(created))
year,month,day,hour,minute,second=time.localtime(created)[:-3]
print("Date created: %02d/%02d/%d %02d:%02d:%02d"%(day,month,year,hour,minute,second))
พิมพ์
somefile.txt
Modified
1429613446
1429613446.0
1429613446.0
Created
1517491049
1517491049.28306
1517491049.28306
Date modified: Tue Apr 21 11:50:46 2015
Date modified: 2015-04-21 11:50:46
Date modified: 21/04/2015 11:50:46
Date created: Thu Feb 1 13:17:29 2018
Date created: 2018-02-01 13:17:29.283060
Date created: 01/02/2018 13:17:29
>>> import os
>>> os.stat('feedparser.py').st_mtime
1136961142.0
>>> os.stat('feedparser.py').st_ctime
1222664012.233
>>>
หากการติดตามลิงก์สัญลักษณ์ไม่สำคัญคุณสามารถใช้os.lstat
builtin ได้
>>> os.lstat("2048.py")
posix.stat_result(st_mode=33188, st_ino=4172202, st_dev=16777218L, st_nlink=1, st_uid=501, st_gid=20, st_size=2078, st_atime=1423378041, st_mtime=1423377552, st_ctime=1423377553)
>>> os.lstat("2048.py").st_atime
1423378041.0
มันอาจคุ้มค่าที่จะดูcrtime
ไลบรารีที่ใช้การเข้าถึงข้ามแพลตฟอร์มกับเวลาในการสร้างไฟล์
from crtime import get_crtimes_in_dir
for fname, date in get_crtimes_in_dir(".", raise_on_error=True, as_epoch=False):
print(fname, date)
# file_a.py Mon Mar 18 20:51:18 CET 2019
debugfs
บน Linux ซึ่งโดยนิยามไม่เสถียรต้องใช้การเข้าถึงรูทระดับบนสำหรับทุกสิ่งและในทุก ๆ ด้านมีแนวโน้มที่จะเป็นหนึ่งในสิ่งที่แม่ของคุณเตือนคุณเสมอ (แต่ใช่มันอาจจะทำงานได้ถ้าคุณหมดหวังจริงๆและเป็น superuser ตัวจริงในระบบที่ไม่มีบูทที่ปลอดภัย…)
os.stat
ไม่รวมถึงเวลาการสร้าง ไม่มีคำจำกัดความของ st_anything สำหรับองค์ประกอบของos.stat()
สิ่งนั้นที่มีเวลา
ลองทำสิ่งนี้:
os.stat('feedparser.py')[8]
เปรียบเทียบกับวันที่สร้างของคุณบนไฟล์ใน ls -lah
พวกเขาควรจะเหมือนกัน
ฉันสามารถรับเวลาการสร้างบน posix ได้โดยการรันคำสั่ง stat ของระบบและแยกเอาต์พุต
commands.getoutput('stat FILENAME').split('\"')[7]
เรียกใช้ stat ภายนอก python จาก Terminal (OS X) ที่ส่งคืน:
805306374 3382786932 -rwx------ 1 km staff 0 1098083 "Aug 29 12:02:05 2013" "Aug 29 12:02:05 2013" "Aug 29 12:02:20 2013" "Aug 27 12:35:28 2013" 61440 2150 0 testfile.txt
... โดยที่ datetime ครั้งที่สี่เป็นการสร้างไฟล์ (แทนที่จะเปลี่ยนเวลา ctime ตามความเห็นอื่น ๆ ที่ระบุไว้)