欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

一篇文章搞懂Python的文件路徑操作

 更新時間:2023年07月07日 15:12:12   作者:碧血灑長空  
這篇文章主要給大家介紹了關(guān)于Python文件路徑操作的相關(guān)資料,在python中我們會經(jīng)常的對文件使用路徑,文件路徑通常有兩種,分別為絕對路徑、相對路徑,需要的朋友可以參考下

前言

如果你要在代碼里讀取一個文件,那么你首先要知道這個文件的路徑。如果只有一個文件,那么很簡單,直接復(fù)制這個文件所在的文件夾路徑及其文件名即可。而在很多情況下,我們會處理大量的文件,這些文件一般都會按一定的規(guī)則存放在一個或幾個文件夾里。本文便是簡單講一下怎么應(yīng)對這種情況,將以Python為例,但其中的理念是通用的。

1 什么是文件路徑

文件路徑簡單地說就是文件的存放位置,它包含具體的盤符號,也就是位于電腦上哪個磁盤分區(qū)、哪個文件夾(目錄)和最終這個文件的名稱+文件類型擴展名。

文件的路徑表示用戶在磁盤上尋找文件時,所歷經(jīng)的文件夾線路;路徑分為絕對路徑相對路徑絕對路徑是從根文件夾開始的路徑;相對路徑是從當(dāng)前文件夾開始的路徑。

1.1 絕對路徑

不同操作系統(tǒng)下絕對路徑的表現(xiàn)形式是不一樣的,以Windows系統(tǒng)為例,一個文件的路徑可能是這樣的:

D:\files\data\ndvi.tif

其中:

  • D:\:表示根文件夾,是文件所在的盤符,即D盤。
  • D:\files\data:表示文件所在的文件夾的路徑,即D盤的files文件夾的子文件夾data。
  • ndvi.tif:表示文件名,其中ndvi是基本名,用來標(biāo)識這個文件;tif是擴展名,用來反映文件的類型,二者用.分開。

Linux和MacOS下的絕對路徑和Windows系統(tǒng)不同,主要區(qū)別如下:

  • 根文件夾不同,Windows的根文件夾是盤符,如D:\、C:\;而在Linux和MacOS中,根文件夾是/,你可以理解為所有的文件都在一個盤下,自然不需要用C、D這樣的字符去區(qū)分了。
  • 分隔符不同,在Windows 上,路徑書寫使用倒斜杠\作為文件夾之間的分隔符。但在MacOS和Linux上,使用正斜杠/作為它們的路徑分隔符。
  • 大小寫區(qū)分不同,文件夾名稱和文件名在Windows和MacOS上是不區(qū)分大小寫的,但在Linux上是區(qū)分大小寫的。

附加卷的路徑:

附加卷,諸如DVD驅(qū)動器或USB閃存驅(qū)動器,在不同的操作系統(tǒng)上顯示也不同。在Windows上,它們表示為新的、帶字符的根驅(qū)動器。諸如D:\E:\。在MacOS上,它們表示為新的文件夾,在/Volumes文件夾下。在Linux上,它們表示為新的文件夾,在/mnt文件夾下。

1.2 相對路徑

相對路徑是指以當(dāng)前工作目錄為參照基礎(chǔ),鏈接到目標(biāo)文件資源(或文件夾)的路徑。

相對路徑的表示符號如下:

  • ./開頭,代表當(dāng)前目錄和文件目錄在同一個目錄里,./也可以省略不寫;
  • ../開頭:向上走一級,代表目標(biāo)文件在當(dāng)前文件所在的上一級目錄;
  • ../../開頭:向上走兩級,代表父級的父級目錄,也就是上上級目錄,再說明白點,就是上一級目錄的上一級目錄;
  • /開頭,代表根目錄。

相對路徑使用示例:

2 Python對路徑的操作

2.1 在Python中怎么表示文件路徑

在Python中,一般使用字符串存儲文件路徑。但需要注意的是,字符反斜杠\在Python中表示轉(zhuǎn)義字符。因此,在表示W(wǎng)indows系統(tǒng)下的文件路徑(Windows系統(tǒng)的分隔符是\)時需注意以下要點:

  • 以路徑D:\files\data\ndvi.tif為例;
  • 在字符串前加個字符r,表示該字符串為原始字符串,會完全忽略所有的轉(zhuǎn)義字符。例如,r"D:\files\data\ndvi.tif";
  • 對轉(zhuǎn)義字符進行轉(zhuǎn)義,例如,"D:\\files\\data\\ndvi.tif";
  • 將分隔符替換為/,是的,在Windows系統(tǒng)下,將分隔符替換為/Python也能正確識別。例如,"D:/files/data/ndvi.tif"。

Linux和MacOS下,直接將路徑放到單引號或者雙引號里就行。

2.2 創(chuàng)建新文件夾

可以用os.mkdir()函數(shù)創(chuàng)建新文件夾(目錄),使用os.path.isdir()函數(shù)判斷一個路徑是不是文件夾,如下所示:

import os

path = "D:/files/data"
if os.path.isdir(path):
	os.mkdir(path)

需要注意的是,os.mkdir()函數(shù)只能創(chuàng)建單級目錄。如上面的代碼所示,只有"D:/files"目錄存在,才能在其下創(chuàng)建data目錄。要想創(chuàng)建多級目錄,則要使用os.makedirs()函數(shù),例如:

import os

path = "D:/files/data"
if os.path.isdir(path):
	os.makedirs(path)

os.listdir()方法用于返回指定的文件夾包含的文件或文件夾的名字的列表,只支持在 Unix, Windows 下使用,例如:

>>> import os
>>> os.listdir("D:/files/data")
['ndvi.tif', 'ndvi_2023_01.tif']

2.3 拼接和拆分文件夾

os.path.join()函數(shù)用于路徑拼接文件路徑,可以傳入多個路徑,它會根據(jù)操作系統(tǒng)的不同自動確定分隔符。

>>> import os
>>> os.path.join(r'D:\files\data', 'ndvi_2023_01.tif')
'D:\\files\\data\\ndvi_2023_01.tif'
>>> os.path.join('D:/files/data', 'ndvi_2023_01.tif')
'D:/files/data\\ndvi_2023_01.tif'
>>> os.path.join('./data', 'ndvi_2023_01.tif')
'./data\\ndvi_2023_01.tif'
>>> os.path.join('files', 'data', 'ndvi_2023_01.tif')
'files\\data\\ndvi_2023_01.tif'

os.path.split()函數(shù)可以把一個路徑拆分為兩部分,后一部分總是最后級別的目錄或文件名。os.path.splitext()函數(shù)同樣可以把一個路徑拆分為兩部分,后一部分總是最后的文件擴展名。

>>> os.path.split("D:/files/data/ndvi.tif")
('D:/files/data', 'ndvi.tif')
>>> os.path.split("D:/files/data")
('D:/files', 'data')
>>> os.path.splitext("D:/files/data/ndvi.tif")
('D:/files/data/ndvi', '.tif')
>>> os.path.splitext("D:/files/data")
('D:/files/data', '')

此外,os.path.basename()函數(shù)用于獲取路徑最后的文件名或文件夾名,os.path.dirname()函數(shù)用于去掉最后的文件名或文件夾名,返回余下的文件夾路徑。

>>> os.path.basename("D:/files/data/ndvi.tif")
'ndvi.tif'
>>> os.path.basename("D:/files/data")
'data'
>>> os.path.dirname("D:/files/data/ndvi.tif")
'D:/files/data'
>>> os.path.dirname("D:/files/data")
'D:/files'

2.4 處理絕對路徑和相對路徑

os.path模塊提供了一些函數(shù),返回一個相對路徑的絕對路徑,以及檢查給定的路徑是否為絕對路徑。

  • os.getcwd():獲取當(dāng)前工作目錄;
  • os.path.abspath(path):返回參數(shù)的絕對路徑的字符串,以當(dāng)前工作目錄為基準(zhǔn)。這是將相對路徑轉(zhuǎn)換為絕對路徑的簡便方法;
  • os.path.isabs(path):如果參數(shù)是一個絕對路徑,就返回True,如果參數(shù)是一個相對路徑,就返回 False;
  • os.path.relpath(path, start):將返回從start路徑到path的相對路徑的字符串。如果沒有提供start,就使用當(dāng)前工作目錄作為開始路徑。

代碼示例:

>>> os.getcwd()
'C:\\Python34'
>>> os.path.abspath('.')
'C:\\Python34'
>>> os.path.abspath('.\\Scripts')
'C:\\Python34\\Scripts'
>>> os.path.isabs('.')
False
>>> os.path.isabs(os.path.abspath('.'))
True
>>> os.path.relpath('C:\\Windows', 'C:\\')
'Windows'
>>> os.path.relpath('C:\\Windows', 'C:\\spam\\eggs')
'..\\..\\Windows'

2.4 使用glob查找文件夾或文件

glob模塊用來查找文件目錄和文件,并將搜索的到的結(jié)果返回到一個列表中。

在使用glob模塊之前,需要先了解一下它的三個通配符,即*、?[],其具體含義如下:

  • *:代表0個或多個字符;
  • ?:代表一個字符;
  • []:匹配指定范圍內(nèi)的字符,如[0-9]匹配數(shù)字;[a-c]匹配字母a、bc,不區(qū)分大小寫;[12a]匹配字母1、2a。

下面通過一個例子詳細講一下這三個通配符怎么使用,假如你有如下所示的目錄結(jié)構(gòu):

+-- D:/
|   +-- data1
|   |   +-- readme.md
|   |   +-- ndvi.tif
|   |   +-- buliding.tif
|   +-- data2
|   |   +-- ndvi.tif
|   |   +-- water.tif
|   +-- picture
|   |   +-- mm.tif
|

假如你要查找data1下的所有以.tif結(jié)尾的文件,你可以這樣寫:

>>> from glob import glob
>>> glob('D:/data1/*.tif')
['D:/data1/ndvi.tif', 'D:/data1/buliding.tif']

假如你要查找data開頭的目錄下的所有名為ndvi.tif的文件,你可以這樣寫:

>>> glob('D:/data*/ndvi.tif')
['D:/data1/ndvi.tif', 'D:/data2/ndvi.tif']
>>> glob('D:/data?/ndvi.tif')
['D:/data1/ndvi.tif', 'D:/data2/ndvi.tif']
>>> glob('D:/data[1-2]/ndvi.tif')
['D:/data1/ndvi.tif', 'D:/data2/ndvi.tif']

3 多個文件的路徑操作示例

在數(shù)據(jù)處理中,很多時候我們都會有這樣的要求,處理多個文件,并且要按照一定的順序。最常見的就是按照時間順序排列各個文件的路徑,比如按年、月、日等,下面詳細介紹幾個例子。

3.1 年尺度數(shù)據(jù)

假如你有如下目錄結(jié)構(gòu):

+-- D:/
|   +-- data
|   |   +-- 2000.tif
|   |   +-- 2001.tif
... ... ... ... ... 
|   |   +-- 2019.tif
|   |   +-- 2020.tif
|

如果你要讀取data目錄下2000-2020年所有文件的路徑(按時間順序排列),你可以這樣寫:

import os
from glob import glob

# glob會自動排序這些文件路徑,排序的規(guī)則為文件名
paths = glob('D:/data/*.tif*')

# 或者這樣寫,可以指定開始和結(jié)束年份
paths = []
root_dir = 'D:/data'
start_year, end_year = 2000, 2020
for year in range(start_year, end_year):
	path = os.path.join(root_dir, f'{year}.tif')
	paths.append(path)

3.2 月尺度數(shù)據(jù)

假如你有如下目錄結(jié)構(gòu):

+-- D:/
|   +-- data
|   |   +-- 200001.tif
|   |   +-- 200002.tif
... ... ... ... ... 
|   |   +-- 200012.tif
|   |   +-- 200101.tif
... ... ... ... ... 
|   |   +-- 202012.tif
|

假如你要讀取data目錄下某一年或某幾年所有月的tif數(shù)據(jù),你可以這樣寫:

import os
from glob import glob
# 讀取2015年所有月的數(shù)據(jù)
year = 2015
paths = glob(f'D:/data/{year}*.tif*')
# 讀取2015-2020年所有月的數(shù)據(jù)
paths = []
root_dir = 'D:/data'
start_year, end_year = 2015, 2020
for year in range(start_year, end_year):
	path += os.path.join(root_dir, f'{year}*.tif')

假如你要讀取data目錄特定年在某個季節(jié)的tif數(shù)據(jù),你可以這樣寫:

import os
from glob import glob
# 假設(shè)一年的冬季為當(dāng)年的1月、2月以及上一年的12月
season_months = {'spring': ['03', '04', '05'], 'summer': ['06', '07', '08'], 
				 'autumn': ['09', '10', '11'], 'winter': ['01', '02']}
paths = []
root_dir = 'D:/data'
season = 'spring'
years = [2014, 2015, 2016]
for year in years:
	months = season_months[season]
	for month in months:
		path = os.path.join(root_dir, 'f{year}{month}.tif')
		assert path
		paths.append(path)
	if season == 'winter':
		path = os.path.join(root_dir, 'f{year-1}{12}.tif')
		assert path
		paths.append(path)

3.3 日尺度數(shù)據(jù)

假如你有如下目錄結(jié)構(gòu),如文件名中的1982001表示數(shù)據(jù)拍攝時間為1982年的第1天。

./ndvi/AVH13C1.A1982001.N07.005.2017161044559.NDVI.tif —— 1982001 —— 1982年第1天
./ndvi/AVH13C1.A1982002.N07.005.2017161050433.NDVI.tif —— 1982002 —— 1982年第2天
./ndvi/AVH13C1.A1982003.N07.005.2017161052408.NDVI.tif —— 1982003 —— 1982年第3天
./ndvi/AVH13C1.A1982004.N07.005.2017161054145.NDVI.tif —— 1982004 —— 1982年第4天
./ndvi/AVH13C1.A1982005.N07.005.2017161055856.NDVI.tif —— 1982005 —— 1982年第5天
./ndvi/AVH13C1.A1982006.N07.005.2017161061328.NDVI.tif —— 1982006 —— 1982年第6天

假如你要讀取某一年年某一月中所有天的數(shù)據(jù)的路徑,你可以這樣寫:

import os
import calendar
from glob import glob
from datetime import datetime

def get_year_month_paths(root_path, year, month):
    '''獲取某年某月所有NDVI文件的路徑'''
    paths = []
    # 用于glob函數(shù)的通配符字符串,可視作文件名模板
    fmt = '*{}{:03}*.tif'
    # 計算該年該月共有多少天
    month_days = calendar.monthrange(year, month)[1]
    # 計算該年該月的第一天是一年中的第幾天
    month_start_day = (datetime(year, month, 1) - datetime(year, 1, 1)).days + 1
    for i in range(month_days):
        day_num = month_start_day + i
        month_day_path = glob(os.path.join(root_path, fmt.format(year, day_num)))
        if not month_day_path:
            print('{}年{}月的數(shù)據(jù)缺失,編號為{}{:03}'.format(year, month, year, day_num))
        paths += month_day_path
    return paths

3.4 文件的時間順序隱藏在文件內(nèi)

有些文件你下載時的默認(rèn)文件名是一堆無意義的字符,而你知道這些文件里存儲的有時間信息,所以就沒有對這些文件一一命名。當(dāng)你要用時你就會發(fā)現(xiàn)很麻煩,要按時間順序讀取這些文件,靠文件名沒法做到,而文件太多,一個個打開看一下時間再重命名又太慢了。這樣只能在代碼里一個個打開文件,讀取其時間,并依據(jù)這些時間對文件的路徑進行排序。這種情況常見于.nc.hdf格式的數(shù)據(jù),其內(nèi)部會存儲時間信息,而有些網(wǎng)站下載文件時文件名有沒有時間信息。

假如你有如下目錄結(jié)構(gòu):

./RH/ked.nc
./RH/mmm.nc
./RH/dii.nc
./RH/jkd.nc
./RH/zex.nc
./RH/xyz.nc

每個nc文件下都有一個名為time的變量,類型為數(shù)組,用于記錄時間。以ERA5數(shù)據(jù)為例,其小時尺度的數(shù)據(jù)記錄的當(dāng)前時間距格里尼治時間1900-01-01-00:00的小時數(shù),若要將其轉(zhuǎn)為東八區(qū)的字符串格式的時間,可以這么做:

import datetime
import netCDF4 as nc

ds = nc.Dataset('./RH/ked.nc')
time = ds['time'][...].data

origin_date = datetime.datetime(1900, 1, 1, 0, 0)
start_date = origin_date+datetime.timedelta(hours=int(times[0])+8)

start_date = start_date.strftime('%Y-%m-%d-%H')

而如果我們不需要對這些nc文件重命名,只是要在代碼里對這些文件的路徑進行排序,只需要這么做:

from glob import glob

nc_paths = glob(os.path.join('./RH', '*.nc'))

times = []
for nc_path in nc_paths:
    # 提取各站點的溫度
    ds = nc.Dataset(nc_path)
    time = ds.variables['time']
    times.append(int(time[0].data))

_, nc_paths = (list(t) for t in zip(*sorted(zip(times, nc_paths))))

最后,對文件路徑進行操作的可能性有無數(shù)種,掌握這些基本知識,學(xué)會舉一反三,多動手嘗試,只有這樣在數(shù)據(jù)處理中才能游刃有余。

總結(jié)

到此這篇關(guān)于Python文件路徑操作的文章就介紹到這了,更多相關(guān)Python文件路徑操作內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論