python工作目錄與文件目錄

工作目錄

文件目錄:文件所在的目錄
工作目錄:執行python命令所在的目錄
在這里插入圖片描述

D:.
|   main.py
|   
+---data
|       data.txt
|       
+---model
|   |   model.py
|   |   train.py
|   |   __init__.py
|   |   
|   +---nlp
|   |   |   bert.py   
|           
\---util|   view.py|   __init__.py

我們以上圖為例,很容易知道main.py的文件目錄是D:/test/main.py,而train.py的文件目錄是D:/test/model/train.py
但是工作目錄是哪個呢?我們打開vscode,可以看到terminal中也顯示了一個目錄D:\test,也就是我們項目的目錄,我們點一下運行,執行了一個python腳本,輸出一個PS D:\test> python -u "d:/test/model/train.py"
在哪里執行的這個腳本呢?D:\test,這就是我們的【工作目錄】

工作目錄可以是任何目錄,只要能通過python運行就行,例如我們打開一個終端執行我們的train.py腳本PS C:\Users\xxx> python D:\test\model\train.py,那么工作目錄就變成了C:\Users\xxx

讀文件

python執行的時候,open函數中相對路徑的會以當前的工作目錄為基準。例如我們再vscode運行腳本,工作目錄是D:\test,那么就可以直接訪問test目錄下的所有文件以及所有子目錄和子目錄下的文件。
如果我們想在main.py訪問data中的data.txt文件,很自然可以寫出如下代碼

with open('data/data.txt') as f:res = f.read()print(res)

但如果我們想在train.py中訪問data.txt目錄怎么辦呢?你可能會用相對路徑寫出如下的代碼

with open('../data/data.txt') as f:res = f.read()print(res)

但是會報如下錯誤

Traceback (most recent call last):
File “d:/test/model/train.py”, line 1, in
with open(‘…/data/data.txt’) as f:
FileNotFoundError: [Errno 2] No such file or directory: ‘…/data/data.txt’

這是因為我們執行train.py文件的目錄D:\testpython會以工作目錄為基準目錄,即D:\test,相對路徑是相對于工作目錄的,因此實際訪問的就是D:\test/../data/data.txt。當然就找不到了。正確的寫法就是

with open('data/data.txt') as f:res = f.read()print(res)

寫文件

我們訓練了一個模型,想要把最終的結果保存在model目錄中,該怎么辦呢?工作目錄依然是D:\test。下面這種寫法依然是錯誤的

with open('tf.pb','w') as f:f.write('hello world')

一定要明白相對路徑是相對于工作目錄來說的,我們執行命令的路徑是D:\test,因此最終寫入的地方就是D:\test\tf.pb,而不是model文件夾,正確的寫法如下

with open('model/tf.pb','w') as f:f.write('hello world')

切換工作目錄

如果我們把工作目錄換掉了,上面的路徑就都不對了,例如在C:\users\xxx目錄下執行python命令,那么上面的路徑就就變成了C:\users\xxx\data\data.txt或者C:\users\xxx\model\tf.pb了,非常的不好用。

  • 查看當前工作目錄os.getcwd()
  • 切換工作目錄 os.chdir(path)

修改train.py和main.py為

import os
cur_dir = os.getcwd()
print(cur_dir)

然后我們打開個終端執行兩個腳本

PS C:\Users\xxx> python d:/test/model/train.py
train.py work dir = C:\Users\xxx
PS C:\Users\xxx> python d:/test/main.py
main.py work dir = C:\Users\xxx

發現他們的工作目錄都是一樣的,重新修改main.py和train.py,并且切換工作目錄

# mian.py
import os
cur_dir = os.getcwd()
print("old work dir = ", cur_dir)
os.chdir(r'D:\\test')
cur_dir = os.getcwd()
print("new work dir = ", cur_dir)
with open('data/data.txt') as f:res = f.read()print(res)
# train.py
import os
cur_dir = os.getcwd()
print("old work dir = ", cur_dir)
os.chdir(r'D:\\test')
cur_dir = os.getcwd()
print("new work dir = ", cur_dir)
with open('model/tf.pb','w') as f:f.write('hello world')

PS C:\Users\xxx> python d:/test/main.py
main.py old work dir = C:\Users\xxx
main.py new work dir = D:\test
hello world

絕對路徑

我個人喜歡以執行文件的路徑作為相對目錄的基準。例如執行main.py文件的時候,喜歡以main.py所在的目錄D:\test為基準,執行train.py的時候,喜歡以train.py所在的目錄D:\test\model為基準,這個時候我們可以先獲取文件的絕對路徑,然后根據這個路徑拼接出我們想要的路徑來, os.path.abspath(__file__)可以獲取文件的絕對路徑,

# main.py
import os
file_path = os.path.abspath(__file__)
file_dir = os.path.dirname(file_path)
print('file_dir=',file_dir)print("cur work dir = ", os.getcwd())data_path = os.path.join(file_dir, 'data/data.txt')
print('data_path=',data_path)
with open(data_path,'r') as f:res = f.read()print(res)

同樣

# train.py
import os
file_path = os.path.abspath(__file__)
file_dir = os.path.dirname(file_path)
print('file_dir=',file_dir)print("cur work dir = ", os.getcwd())
# 
model_path = os.path.join(file_dir, 'tf.pb')
print('model_path=',model_path)
with open(model_path,'w') as f:f.write('hello world')

PS C:\Users\xxx> python d:/test/model/train.py
file_dir= d:\test\model
cur work dir = C:\Users\xxx
model_path= d:\test\model\tf.pb

很直觀了,我們根據文件的目錄拼接出我們想要的目錄,然后執行讀寫操作。

導入自定義包/文件

我們util目錄中有一個view.py的文件,里面包含了一些工具類和方法

# view.py
class View:def __init__(self, x, y):self.x = xself.y = y

我們想要在train.py中調用該怎么辦呢?

import util.view import View 

我們以D:\test為工作目錄,執行train.py文件,嘿嘿

Traceback (most recent call last):
File “d:/test/model/train.py”, line 1, in
from util.view import View
ModuleNotFoundError: No module named ‘util’

這是因為python在導入包的時候import xxx是以文件路徑為基準的,即以train.py為基準,發現train.py的目錄中并沒有util子目錄,因此導入失敗。聰明的你做了一個簡單的修改

import ..util.view import View 

發現報了另一個錯誤

Traceback (most recent call last):
File “d:/test/model/train.py”, line 1, in
from …util.view import View
ValueError: attempted relative import beyond top-level package

這是因為python規定頂層模塊不能作為package,我們執行的是train.py文件,那么train.py所在的目錄就是頂層模塊了,train.py相對導入的的目錄不在超出了train.py所在目錄,因此導入失敗。換句話說就是相對導入只能導入同一個package下的子package或module。

# main.py
import model.train
#train.py
import util.view import View 

這種方式依然會報錯,雖然我們執行的時main.py文件,但是導入model.train的時候依然會執行train.py文件。
總結一下:

  1. 相對路徑導入時是以當前文件為基準的,當前文件所在的目錄就是頂層模塊目錄
  2. 相對導入模塊不能超出頂層目錄,意味者相對導入只能導入當前文件所在目錄下的模塊或者子package

非常的疑惑,什么時候可以使用..

包查詢路徑

相對路徑只能導入同一package下的module。要導入不同package下的module可以使用絕對路徑。這就非常奇怪了,我們安裝的三方庫為什么可以在任意文件導入呢?這就不得不說python的庫查詢機制,python回去默認的一些地方查找安裝的package,具體可以通過sys.path來查看

import sysfor path in sys.path:print(path)

d:\test\model
D:\soft\python3\python37.zip
D:\soft\python3\DLLs
D:\soft\python3\lib
D:\soft\python3
C:\Users\xxx\AppData\Roaming\Python\Python37\site-packages
C:\Users\xxx\AppData\Roaming\Python\Python37\site-packages\win32
C:\Users\x\xxAppData\Roaming\Python\Python37\site-packages\win32\lib
C:\Users\x\xxAppData\Roaming\Python\Python37\site-packages\Pythonwin
D:\soft\python3\lib\site-packages

可以看到除了第一條路徑,其余都是跟python的默認安裝路徑有關。python會按順序從這些路徑里面查找我們安裝的package,越靠前的優先級越高。例如我們導入import os這個庫優先從項目路徑d:\test查找os的庫,沒有找到就接著從第二個路徑查找,一直找到D:\soft\python3\Lib發現有os的庫,然后導入。如果我們自己的項目中有一個os的庫,就會優先使用項目中的,替換掉lib里面的。

sys.path絕對路徑導入自己的包

我們把自己的package也加入到sys.path中,python就可以找到了,一種簡單的方法就是

#train.py
import os
import sys
cur_dir = os.path.dirname(os.path.abspath(__file__))# 直接導入會找不到模塊
#import util.view# util模塊在test目錄下,我們把test目錄添加到sys.path中
sys.path.append(os.path.dirname(cur_dir))for path in sys.path:print(path)import util.view# nlp在model下面,sys.path的第一個路徑就是d:\test\model
# 可以在d:\test\model下面發現有一個nlp的package,導入成功
from nlp.bert import BERT

sys.path相對路徑導入自己的包

sys.path添加相對路徑的時候,以哪個目錄為基準目錄呢?答案是【工作目錄】,我們是在d:\test目錄下執行的命令train.py,所以工作目錄就是d:\test,而util包就是在d:\test下面的,所以我們

#train.py
import sys
sys.path.append(".")
for path in sys.path:print(path)
import util.view

忽略python自己的目錄,我們可以看到當前有sys.path有兩個目錄,第一個是d:\test\model,也就是【文件路徑】,python會自動把執行的文件的路徑加進來,所以文件目錄下的所有package和module都可以通過相對目錄的方式找到。第二個是一個.,這個就是工作目錄。因為我們使用的是相對路徑導入,而相對路徑的基準目錄就是d:\test.代表的就是基準目錄。

d:\test\model
.

使用絕對路徑打印更直觀一些

# train.py
import sys
import os
sys.path.append(".")
for path in sys.path:print(os.path.abspath(path))
import util.view

d:\test\model
d:\test

d:\test添加到了sys.path中,因此d:\test下面的package就都可以訪問到了。很明顯相對路徑很不好用,當我們把工作目錄切換到C:\users\xxx的時候,就又找不到了

PS C:\Users\xxx> python d:/test/model/train.py
d:\test\model
D:\soft\python3\python37.zip
D:\soft\python3\DLLs
D:\soft\python3\lib
D:\soft\python3
C:\Users\xxx\AppData\Roaming\Python\Python37\site-packages
C:\Users\xxx\AppData\Roaming\Python\Python37\site-packages\win32
C:\Users\xxx\AppData\Roaming\Python\Python37\site-packages\win32\lib
C:\Users\xxx\AppData\Roaming\Python\Python37\site-packages\Pythonwin
D:\soft\python3\lib\site-packages
C:\Users\xxx

Traceback (most recent call last):
File “d:/test/model/train.py”, line 6, in
import util.view
ModuleNotFoundError: No module named ‘util’

所以我們最好使用絕對路徑來添加

小結

核心訴求就是找到package,為什么會找不到我們自己定義的package呢?因為沒有把路徑添加到python的包搜索路徑里面,怎么添加呢?使用sys.path.append添加。定位到package的絕對路徑,然后添加進去。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/38253.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/38253.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/38253.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

計算機網絡期末復習(大題+小題)

計算機網絡期末復習 一、計算機網絡概述 Point 1 計算機網絡就是以傳輸信息為基本目的,用通信線路和通信設備將多個計算機連接起來的計算機系統的集合。由自治的計算機互聯起來的結合體。 Point 2 按網絡的覆蓋范圍進行分類 (1)局域網*…

解鎖Transformer的魯棒性:深入分析與實踐指南

🛡? 解鎖Transformer的魯棒性:深入分析與實踐指南 Transformer模型自從由Vaswani等人在2017年提出以來,已經成為自然語言處理(NLP)領域的明星模型。然而,模型的魯棒性——即模型在面對異常、惡意或不尋常…

人機交互新維度|碩博電子發布雙編碼器操作面板、無線操作面板等新品

6月15日,碩博電子召開了一場新品發布會,向業界展示了多項前沿技術成果,其中備受矚目的當屬SPM-KEYP-D08雙編碼器操作面板、SPM-KEYP-D16W無線操作面板、SPR-HT-XK12A無線手持發射端以及SPQ-WT-B01灑水車專用控制面板。這些創新產品的亮相&…

文心一言 VS 訊飛星火 VS chatgpt (292)-- 算法導論21.3 5題

五、證明:任何具有 m 個 MAKE-SET、UNION 和 FIND-SET 操作的序列,這里所有的 LINK 操作都出現在 FIND-SET 操作之前,如果同時使用路徑壓縮和按秩合并啟發式策略,則這些操作只需 O(m) 的時間。在同樣情況下,如果只使用…

Class Constructors and Destructors (類的構造函數和析構函數)

Class Constructors and Destructors [類的構造函數和析構函數] 1. Declaring and Defining Constructors (聲明和定義構造函數)2. Using Constructors (使用構造函數)3. Default Constructors (默認構造函數)4. Destructors (析構函數)5. Improving the Stock Class (改進 Sto…

MT1597 平行線

題目 用下面的數據類型表示線: struct POINT { //點 int x, y; //坐標值x和y } ; struct LINE { //線 POINT s, e; //線的兩端 } ; 輸入2個線段的端點的坐標值x和y,判斷兩條線段所在直線是否為平行線。如果兩線段共線,判為不平行。 輸入…

強強聯合:Apache Kylin與Impala的集成之道

🔗 強強聯合:Apache Kylin與Impala的集成之道 在大數據時代,Apache Kylin和Impala都是分析型數據庫的佼佼者,分別以預計算的OLAP引擎和高性能的SQL on Hadoop解決方案而聞名。將兩者集成,可以充分利用Kylin的預計算能…

C程序設計譚浩強第五版

第三章 程序習題 1、第2題2、第2題3、第3題4、第4題 1、第2題 假如我國國民生產總值的年增長率為7%, 計算10年后我國國民生產總值與現在相比增長多少百分比。計算公式為 p ( 1 r ) n p (1r)^n p(1r)n ,其中r為年增長率,n為年數,p為與現在…

thinkphp通過with查詢,并通過關聯表進行篩選

直接添加一個where條件,然后條件里面用表名.字段即可,非常方便 需要注意的一點是在fastadmin里面,$this->auth->getGroupIds()這樣獲取是會獲取到緩存里面的值,必須重新登錄之后才可以得到最新的用戶組,這個問題導致困擾了我一晚上 $usage $this->model->with([us…

Oracle數據庫教程

Oracle數據庫教程 大家好,我是免費搭建查券返利機器人省錢賺傭金就用微賺淘客系統3.0的小編,也是冬天不穿秋褲,天冷也要風度的程序猿!今天我們將深入探討Oracle數據庫的基礎知識、特性以及在Java中的應用。 什么是Oracle數據庫&…

前端小案例,用錨點(哈希值)實現Tab組件切換

在前端開發的世界里,使用現代化的技術和方法來實現常見的組件是非常重要的。今天,我們將通過一個具體的案例來展示如何使用現代化的CSS和ES6來創建一個優雅且功能豐富的Tab組件。本文將詳細介紹實現思路、代碼分析,并提供一些實用的開發技巧。…

25 防火墻基礎操作

1 防火墻進入WEB頁面操作 華三防火墻的默認用戶:admin/密碼:admin 將IP地址改在同一網段的信息 在防火墻的管理地址 GE/0/0/1:192.168.0.1 主機的地址是:192.168.0.101 思考一下為什么Ping不通 security-zone name Management import interface GigabitEthernet1/…

音視頻開發34 FFmpeg 編碼- 將h264和acc文件打包成flv文件

FFmpeg合成流程 示例本程序會?成?個合成的?頻和視頻流,并將它們編碼和封裝輸出到輸出?件,輸出格式是根據?件 擴展名?動猜測的。 示例的流程圖如下所示。 ffmpeg 的 Mux 主要分為 三步操作: avformat_write_header : 寫?…

Qt WPS(有源碼)

項目源碼地址:WPS完整源碼 一.項目詳情 該項目仿照WPS,實現了部分的功能,能夠很方便對文本和HTML進行修改,并且有打印功能,可以很方便的生成PDF。 應用界面 項目架構分析 這個項目主要可分為兩個部分,一…

使用RNN模型構建人名分類器

使用RNN模型構建人名分類器 1 項目需求和實現分析 短文本分類問題 2 數據處理三部曲 場景1:數據處理三部曲示意圖 場景2:三個字母onehot編碼形狀分析 3 構建RNN模型 4 構建訓練函數并進行訓練 - 有關模型、損失函數、優化器三者在pytorch中的表示 5…

葉老師的新水杯c++

題目描述 最近葉老師換了個帶吸管的水杯。 貝貝發現當葉老師使用帶吸管的水杯時,每天會喝 x 毫升的水。而使用不帶吸管的水杯時,每天會喝 y 毫升的水。 請問在 n 天的時間內,葉老師喝水量的上限與下限相差多少? 輸入 第一行為…

聚焦Python分布式爬蟲必學框架Scrapy打造搜索引擎(一)

Scrapy綜述 Scrapy總體架構 Scrapy架構圖(綠線是數據流向) 適用于海量靜態頁面的數據下載 Scrapy Engine(引擎): 負責Spider、ItemPipeline、Downloader、Scheduler中間的通訊,信號、數據傳遞等。 Scheduler(調度器): 它負責接受引擎發送過來的Request請求&…

java.io.PrintStream介紹

java.io.PrintStream 是 Java 標準庫中的一個類,用于輸出流中的打印。它提供了一組方便的方法,用于格式化輸出和寫入數據。PrintStream 類中最常見的使用方式是通過 System.out 和 System.err 進行標準輸出和錯誤輸出。 System.out 和 System.err 都是 …

ELK 企業實戰7

ELKkafkafilebeat企業內部日志分析系統 1、組件介紹 1、Elasticsearch: 是一個基于Lucene的搜索服務器。提供搜集、分析、存儲數據三大功能。它提供了一個分布式多用戶能力的全文搜索引擎,基于RESTful web接口。Elasticsearch是用Java開發的&#xff…

【linux】chmod修改文件權限詳解

目錄 一.linux中默認的文件權限 二.文件權限類別 三.chmod改變權限的兩種方式 一.linux中默認的文件權限 默認文件權限: 當你新建一個文件時,文件會有一個默認的權限,這個默認權限就是umask的值,umask一般默認是022,這個值設…