復習,os模塊,導入模塊import和from


一、復習

collections
  增加了一些擴展數據類型 :namedtuple orderdict defaltdict
隊列和棧
time 時間
  三種格式 : 時間戳 結構化 字符串
random
  隨機數 打亂順序
sys
  和python解釋器交互的:
    path 導入模塊的時候 從這個路徑中獲取
    argv 以腳本的形式執行一個文件的時候,可以加一些參數

    import sys
    print(sys.argv) #['xx.py','alex','sb']

 

學習方法:
先把老師的代碼敲一遍,並把代碼逐一注釋
再開一個新文件,根據注釋,還原代碼

 

昨日作業講解:

y-m-d h:M:S 比如2017-07-08 10:23:41
從當前時間開始 比起y-m-d h:M:S過去了多少年 多少月 多少天 多少小時,多少分,多少秒

步驟分解

當前的時間 時間戳
過去的時間 轉成時間戳
時間戳相減
相減之后的結果轉成結構化時間
結構化時間 - 1970.1.1 0:0:0  #英國時間

先來解釋一下結構化時間,有2種方式,分別是

import time
struct_time = time.localtime(0)
ret = time.strftime('%Y-%m-%d %H:%M:%S',struct_time)
print(ret)  # 中國結構化時間

struct_time = time.gmtime(0)
ret = time.strftime('%Y-%m-%d %H:%M:%S',struct_time)
print(ret) # 英國結構化時間

執行輸出:

1970-01-01 08:00:00
1970-01-01 00:00:00

 

那么為什么要用英國時間呢?

因為英國時間的時分秒都是0,沒有數字比0更小了。

但如果用中國時間,那么比8小的數字,就會出現負數,比如7:30

所以說,用英國時間,是最准確的。由於時分秒都是0,所以不需要相減

import time
def cal_time(fmt_time,fmt):
    now = time.time()
    time_before = time.mktime(time.strptime(fmt_time,fmt))
    sub_time = now - time_before
    struct_time = time.gmtime(sub_time)
    return '過去了%d年%d月%d天%d小時%d分鍾%d秒' % \
    (struct_time.tm_year - 1970, struct_time.tm_mon - 1,
                                       struct_time.tm_mday - 1, struct_time.tm_hour,
                                       struct_time.tm_min, struct_time.tm_sec)

ret = cal_time('2018-4-23 10:30:20','%Y-%m-%d %H:%M:%S')
print(ret)

執行輸出:

過去了0年0月2天4小時20分鍾51秒

 

要求 生成隨機驗證碼
基礎需求: 6位數字驗證碼 數字可以重復
進階需求: 字母+數字 4位驗證碼 數字字母都可以重復

這是一道面試題

完成第一個基礎需求

import random
def id_code(num):
    ret = ''  # 定義空字符串
    for i in range(num):
        n = random.randint(0,9)  # 數字由0~9組成
        ret += str(n)  # 將數字轉換為字符串,並拼接
    return ret
print(id_code(6))

執行輸出:

803296

 

完成進階需求

有一個難點,如果獲取所有的大小寫字母,全手寫一遍?太Low了

這個時候,就需要用到ascii碼。

import random
def id_code(num):   # num 大寫字母 小寫字母在每一位被取到的概率相同
    ret = ''
    for i in range(num):
        number = str(random.randint(0,9))   # 所有數字
        alph_num = random.randint(97,122)   # a97 z122 +25 所有小寫字母
        alph_num2 = random.randint(65,90)   # A65 Z97 +25  所有大寫字母
        alph = chr(alph_num)  # 大寫
        alph2 = chr(alph_num2) # 小寫
        choice = random.choice([number,alph,alph2])  # 數字,大寫,小寫。每種是1/3的幾率
        ret += choice  # 組合字符串
    return ret
print(id_code(6))  # 取6位

執行輸出:

01J98C

 

額外一個需求,字母和數字,取50%的概率

import random
def id_code(num):   # num 大寫字母 小寫字母在每一位被取到的概率相同
    ret = ''
    for i in range(num):
        number = str(random.randint(0,9))   # 所有數字
        alph_num = random.randint(97,122)   # a97 z122 +25 所有小寫字母
        alph_num2 = random.randint(65,90)   # A65 Z97 +25  所有大寫字母
        alph = chr(alph_num)  # 大寫
        alph2 = chr(alph_num2) # 小寫
        choice = random.choice([alph, alph2])  # 字母大小寫,取50%的概率
        choice = random.choice([number,choice])  # 數字和字母,取50%的概率
        ret += choice  # 組合字符串
    return ret
print(id_code(6))  # 取6位

執行輸出:

Q4I17t

 

二、os模塊

os模塊是與操作系統交互的一個接口

 

當前執行的這個python文件目錄相關的工作路徑

os.getcwd() 獲取當前工作目錄,即當前python腳本工作的目錄路徑
os.chdir("dirname")  改變當前腳本工作目錄;相當於shell下cd
os.curdir  返回當前目錄: ('.')
os.pardir  獲取當前目錄的父目錄字符串名:('..')

和文件夾相關的

os.makedirs('dirname1/dirname2')    可生成多層遞歸目錄
os.removedirs('dirname1')    若目錄為空,則刪除,並遞歸到上一級目錄,如若也為空,則刪除,依此類推
os.mkdir('dirname')    生成單級目錄;相當於shell中mkdir dirname
os.rmdir('dirname')    刪除單級空目錄,若目錄不為空則無法刪除,報錯;相當於shell中rmdir dirname
os.listdir('dirname')    列出指定目錄下的所有文件和子目錄,包括隱藏文件,並以列表方式打印

和文件相關的

os.remove()  刪除一個文件
os.rename("oldname","newname")  重命名文件/目錄
os.stat('path/filename')  獲取文件/目錄信息

和操作系統差異相關的

os.sep    輸出操作系統特定的路徑分隔符,win下為"\\",Linux下為"/"
os.linesep    輸出當前平台使用的行終止符,win下為"\t\n",Linux下為"\n"
os.pathsep    輸出用於分割文件路徑的字符串 win下為;,Linux下為:
os.name    輸出字符串指示當前使用平台。win->'nt'; Linux->'posix'

和執行系統命名相關的

os.system("bash command")  運行shell命令,直接顯示
os.popen("bash command).read()  運行shell命令,獲取執行結果

和環境變量相關的

os.environ  獲取系統環境變量

 

和操作系統路徑相關的os.path

os.path.abspath(path) 返回path規范化的絕對路徑 
os.path.split(path) 將path分割成目錄和文件名二元組返回 
os.path.dirname(path) 返回path的目錄。其實就是os.path.split(path)的第一個元素 
os.path.basename(path) 返回path最后的文件名。如果path以/或\結尾,那么就會返回空值。
                        即os.path.split(path)的第二個元素
os.path.exists(path)  如果path存在,返回True;如果path不存在,返回False
os.path.isabs(path)  如果path是絕對路徑,返回True
os.path.isfile(path)  如果path是一個存在的文件,返回True。否則返回False
os.path.isdir(path)  如果path是一個存在的目錄,則返回True。否則返回False
os.path.join(path1[, path2[, ...]])  將多個路徑組合后返回,第一個絕對路徑之前的參數將被忽略
os.path.getatime(path)  返回path所指向的文件或者目錄的最后訪問時間
os.path.getmtime(path)  返回path所指向的文件或者目錄的最后修改時間
os.path.getsize(path) 返回path的大小

 

注意:os.stat('path/filename')  獲取文件/目錄信息 的結構說明

stat 結構:

st_mode: inode 保護模式
st_ino: inode 節點號。
st_dev: inode 駐留的設備。
st_nlink: inode 的鏈接數。
st_uid: 所有者的用戶ID。
st_gid: 所有者的組ID。
st_size: 普通文件以字節為單位的大小;包含等待某些特殊文件的數據。
st_atime: 上次訪問的時間。
st_mtime: 最后一次修改的時間。
st_ctime: 由操作系統報告的"ctime"。在某些系統上(如Unix)是最新的元數據更改的時間,在其它系統上(如Windows)是創建時間(詳細信息參見平台的文檔)。
stat 結構

 

 舉例:

獲取當前工作目錄,即當前python腳本工作的目錄路徑

import os
print(os.getcwd())

執行輸出:

E:\python_script\day26

 

改變當前腳本工作目錄;相當於shell下cd

注意:文件不會移動,只是內存的值改變了

import os
print(os.getcwd())
os.chdir("D:\\")
print(os.getcwd())

執行輸出:

E:\python_script\day26
D:\

 

返回當前目錄: ('.')

import os
print(os.curdir)

執行輸出: .

返回結果是一個點,表示當前路徑

 

獲取當前目錄的父目錄字符串名:('..')

import os
print(os.pardir)

執行輸出: ..

返回結果是2個點,表示上一級目錄

在linux里面,每一個文件夾,使用ls -l 時,會出現點和點點

 

生成單級目錄;相當於shell中mkdir dirname

import os
os.mkdir('dirname/son_dir')

如果文件不存在,就報錯:

FileNotFoundError: [WinError 3] 系統找不到指定的路徑。: 'dirname/son_dir'

 

可生成多層遞歸目錄

import os
os.makedirs('dirname/son_dir')

執行程序,就會發現多了一個目錄dirname\son_dir

如果文件不存在,會自動創建。

 

刪除單級空目錄,若目錄不為空則無法刪除,報錯;相當於shell中rmdir dirname

import os
os.rmdir('dirname/son_dir')

執行程序,就會發現dirname目錄下的son_dir文件夾,不存在了。

 

 

若目錄為空,則刪除,並遞歸到上一級目錄,如若也為空,則刪除,依此類推

在dirname目錄下創建a目錄,a目錄下再創建c目錄,c目錄下再創建d目錄

import os
os.removedirs('dirname/a/b/c/d')

執行程序

可以發現,連dirname也被刪除掉了

 

 列出指定目錄下的所有文件和子目錄,包括隱藏文件,並以列表方式打印

import os
print(os.listdir('E:\python_script\day26'))

執行輸出:

['example.ini', 'file1', 'file2', 'new2.ini', 'test.log', 'test.py', 'userinfo.log', '隨機碼.py']

 

獲取文件/目錄信息 的結構說明

import os
print(os.stat(r'E:\python_script\day26\new2.ini'))

執行輸出:

Pycharm小技巧:

當輸出的內容,一行顯示過長時。可以按左邊紅色方框的按鈕,它會自動換行顯示。

 

r'E:\python_script\day26\new2.ini'  前面的r表示轉義

'r'是防止字符轉義的 如果路徑中出現'\t'的話 不加r的話\t就會被轉義 而加了'r'之后'\t'就能保留原有的樣子

 否則執行報錯


輸出字符串指示當前使用平台。win->'nt'; Linux->'posix'

print(os.name)

執行輸出:nt

 

import os
if os.name == 'nt':
    path = 'python\\2.mok.py'  # windows文件路徑,加雙斜杠
elif os.name == 'posix':
    path = 'python/2.mok.py'

print(path)

windows執行輸出:

python\2.mok.py

 

優化代碼:

path = 'python%s2.mok.py'%os.sep
print(path)

windows執行輸出:

python\2.mok.py

 

os.system

運行shell命令,直接顯示

test.py代碼如下:

import os
print(os.system("dir"))  # windows顯示目錄中的文件和子目錄列表

執行程序,顯示亂碼

 

 os.popen運行shell命令,獲取執行結果

修改test.py文件,內容如下:

import os
print(os.popen("dir").read()) 

執行程序:

 

獲取系統環境變量

import os
print(os.environ)

執行輸出:

environ({'COMMONPROGRAMW6432': 'C:\\Program Files\\Common Files', 'LOGONSERVER': 

...

 

重點要掌握的,有以下這些:

os.getcwd() 獲取當前工作目錄,即當前python腳本工作的目錄路徑
os.mkdir('dirname')    生成單級目錄;相當於shell中mkdir dirname
os.makedirs('dirname1/dirname2')    可生成多層遞歸目錄
os.listdir('dirname')    列出指定目錄下的所有文件和子目錄,包括隱藏文件,並以列表方式打印
os.name    輸出字符串指示當前使用平台。win->'nt'; Linux->'posix'
os.sep    輸出操作系統特定的路徑分隔符,win下為"\\",Linux下為"/"
os.system("bash command")  運行shell命令,直接顯示
os.popen("bash command).read()  運行shell命令,獲取執行結果

  

path系列

返回path規范化的絕對路徑

import os
print(os.path.abspath('test.log'))

執行輸出:

E:\python_script\day26\test.log

 

將path分割成目錄和文件名二元組返回 

import os
print(os.path.split(os.path.abspath('test.log')))

執行輸出:

('E:\\python_script\\day26', 'test.log')

 

返回path的目錄。其實就是os.path.split(path)的第一個元素 

import os
print(os.path.dirname(os.path.abspath('test.log')))

執行輸出:

E:\python_script\day26

 

返回path最后的文件名。如果path以/或\結尾,那么就會返回空值。
即os.path.split(path)的第二個元素

import os
print(os.path.basename(os.path.abspath('test.log')))

執行輸出:

test.log

 

如果path存在,返回True;如果path不存在,返回False

import os
print(os.path.exists(r'E:\python_script\day26\test.log'))

執行輸出: True

 

如果path是絕對路徑,返回True

import os
print(os.path.isabs(r'E:\python_script\day26\test.log'))

執行輸出: True

 

如果path是一個存在的文件,返回True。否則返回False

import os
print(os.path.isfile(r'E:\python_script\day26\test.log'))

執行輸出: True

 

如果path是一個存在的目錄,則返回True。否則返回False

import os
print(os.path.isdir(r'E:\python_script\day26\test.log'))

執行輸出:

False

 

將多個路徑組合后返回,第一個絕對路徑之前的參數將被忽略

import os
print(os.path.join(r'E:\python_script\day26','test.log'))

執行輸出:

E:\python_script\day26\test.log

 

返回path所指向的文件或者目錄的最后訪問時間

import os
print(os.path.getatime(r'E:\python_script\day26\test.log'))

執行輸出:

1524498744.3853774

 

返回path所指向的文件或者目錄的最后修改時間

import os
print(os.path.getmtime(r'E:\python_script\day26\test.log'))

執行輸出:

1524499380.404139

 

返回path的大小

import os
print(os.path.getsize(r'E:\python_script\day26'))

執行輸出:

4096

用getsize 統計文件夾小大,是不准的,windows永遠是4096

統計文件是准確的

import os
print(os.path.getsize(r'E:\python_script\day26\test.log'))

執行輸出:

1692

 

三、導入模塊import和from

1. 什么是模塊?

一個模塊就是一個包含了python定義和聲明的文件,文件名就是模塊名字加上.py的后綴。
2. 為何要使用模塊?

如果你退出python解釋器然后重新進入,那么你之前定義的函數或者變量都將丟失,因此我們通常將程序寫到文件中以便永久保存下來,需要時就通過python test.py方式去執行,此時test.py被稱為腳本script
3.如何使用模塊?

import

示例文件:自定義模塊my_module.py,文件名my_module.py,模塊名my_module

my_module.py文件內容如下:

print('from the my_module.py')

demo.py文件內容如下:

import my_module

為什么這段代碼,Pycharm會飄紅呢?

 

因為我的Pycharm的工作目錄為E:\python_script

 而代碼所在的目錄為E:\python_script\day26

在工作目錄下面,找不到my_module文件,所以報錯

為了解決這個,需要點擊file->open 選擇文件夾為E:\python_script\day26

點擊Open in current windows->ok

在新窗口中,點擊deme.py文件,就不會飄紅了。

 

執行demo.py文件

程序輸出:

from the my_module.py

 

 what ?為什么執行了?

導入一個模塊,相當於這個模塊從上到下依次被執行了

一個模塊,會不會被多次導入呢?

 修改demo.py文件,內容如下:

import my_module
import my_module
import my_module

執行輸出:

from the my_module.py

說明只導入了一次

同一個模塊不會被多次導入

總結:

模塊可以包含可執行的語句和函數的定義,這些語句的目的是初始化模塊,它們只在模塊名第一次遇到導入import語句時才執行(import語句是可以在程序中的任意位置使用的,且針對同一個模塊很import多次,為了防止你重復導入,python的優化手段是:第一次導入后就將模塊名加載到內存了,后續的import語句僅是對已經加載大內存中的模塊對象增加了一次引用,不會重新執行模塊內的語句)

 我們可以從sys.modules中找到當前已經加載的模塊,sys.modules是一個字典,內部包含模塊名與模塊對象的映射,該字典決定了導入模塊時是否需要重新導入。

 

 修改my_module.py,內容如下:

print('from the my_module.py')

def func():
    print('in func')

那demo.py如何調用呢?修改demo.py文件

import my_module

my_module.func()  # 執行函數

執行輸出:

from the my_module.py
in func

 

import 的 過程
import一個模塊的時候,首先創建一個屬於my_module的內存空間
加載my_module模塊中所有的代碼
將my_module模塊中的名字方法放在my_module的命名空間里

 

my_module.py增加一個變量,修改文件,內容如下:

print('from the my_module.py')
money = 100

def func1():
    print('in func')
    
def func2():
    print('in func2')

修改demo.py,調用func2和money

import my_module

my_module.func2()
print(my_module.money)

執行輸出:

from the my_module.py
in func
100

 

demo.py里面也創建一個func1和money

那么調用時,它會調用誰呢?

import my_module

money = 200

def func1():  # func1函數名不沖突
    print('in my func1')

my_module.func1()  # 執行my_module模塊中的func1函數
func1()  # 執行當前模塊中的func1函數
print(money)

執行輸出:

from the my_module.py
in func
in my func1
200

從結果中,可以看出,函數func1調用的是當前模塊中的。

 

每個模塊都是一個獨立的名稱空間,定義在這個模塊中的函數,把這個模塊的名稱空間當做全局名稱空間,這樣我們在編寫自己的模塊時,就不用擔心我們定義在自己模塊中全局變量會在被導入時,與使用者的全局變量沖突

 

總結:首次導入模塊my_module時會做三件事:

1.為源文件(my_module模塊)創建新的名稱空間,在my_module中定義的函數和方法若是使用到了global時訪問的就是這個名稱空間。

2.在新創建的命名空間中執行模塊中包含的代碼,見初始導入import my_module

提示:導入模塊時到底執行了什么?

In fact function definitions are also ‘statements’ that are ‘executed’; the execution of a module-level function definition enters the function name in the module’s global symbol table.
事實上函數定義也是“被執行”的語句,模塊級別函數定義的執行將函數名放入模塊全局名稱空間表,用globals()可以查看

3.創建名字my_module來引用該命名空間

這個名字和變量名沒什么區別,都是‘第一類的’,且使用my_module.名字的方式可以訪問my_module.py文件中定義的名字,my_module.名字與test.py中的名字來自兩個完全不同的地方。

 

為模塊名起別名,相當於m1=1;m2=m1

相當於內存名改名了,原來的名字就不能用了

import my_module as mm
print(mm.money)
print(my_module.money)  # 這里就不能用my_module

執行輸出:

from the my_module.py
100

 

為什么要起別名呢?
1.模塊名太長的可以起別名

2.有特殊需求

 

現在有一個需求,用戶可以選擇json或者pickle

import pickle
import json
inp = input('json or pickle>>> ').split()
if inp == 'json':
    json.dumps({'k':'v'})
elif inp == 'pickle':
    pickle.dumps({'k':'v'})

那么問題來了,有多處調用
代碼都復制一遍?太low了

改用別名的方式:

inp = input('json or pickle>>> ').strip()

if inp == 'json':
    import json as m
elif inp == 'pickle':
    import pickle as m
else:
    print('未定義!')

a = m.dumps({'k':'v'})
print(a)

執行輸出:

json or pickle>>> json
{"k": "v"}

這樣看來,代碼就精簡了

 

還有一個場景,數據庫方面的

有兩中sql模塊mysql和oracle,根據用戶的輸入,選擇不同的sql功能

#mysql.py
def sqlparse():
    print('from mysql sqlparse')
#oracle.py
def sqlparse():
    print('from oracle sqlparse')

#test.py
db_type=input('>>: ')
if db_type == 'mysql':
    import mysql as db
elif db_type == 'oracle':
    import oracle as db

db.sqlparse()

 

在一行導入多個模塊

import os,sys,time

可以這么寫,但是不推薦,一行導入多個模塊
根據PEP8規范,不建議一行多個模塊
一個縮進是4個空格

推薦一行一個模塊

import os
import sys
import time

總結:

PEP8
每一行import 應該導入一個模塊
如果不是必要的需求,所有的模塊都應該在文件的頂端導入
關於導入模塊的順序 先導入內置的 再導入擴展 最后導入自定義

import
導入模塊: 模塊的名字要符合變量的定義規范
           不要起你知道的內置的名字的模塊
模塊不會被多次導入
導入模塊相當於
    開辟了一個新的空間
    執行被導入模塊中的代碼
    創建一個模塊名作為這塊空間的引用
導入的模塊中的名字和全局文件中的名字不會沖突
import 。。。 as 。。。
導入多個模塊 import a,b,c

PEP8規范
每一行import 應該導入一個模塊
如果不是必要的需求,所有的模塊都應該在文件的頂端導入
關於導入模塊的順序 先導入內置的 再導入擴展 最后導入自定義

  

from ... import...

從my_module導入money變量

修改demo.py,內容如下:

from my_module import money

執行輸出:

from the my_module.py

為啥會輸出上面那段話呢?

因為代碼是從上向下執行,from也是把代碼執行完了

 

獲取my_module模塊中的money變量

修改demo.py,內容如下:

from my_module import money
print(money)

執行輸出:

from the my_module.py
100

 

添加同名的變量money

修改demo.py,內容如下:

from my_module import money
print(money)
money = 20
print(money)

執行輸出:

from the my_module.py
100
20

說明,如果當前有重名,變量會覆蓋

 

增加同名的func1,改變代碼位置:

def func1():
    print('in demo')
from my_module import money
func1()

執行輸出:

from the my_module.py
in demo

 

對比import my_module,會將源文件的名稱空間'my_module'帶到當前名稱空間中,使用時必須是my_module.名字的方式

而from 語句相當於import,也會創建新的名稱空間,但是將my_module中的名字直接導入到當前的名稱空間中,在當前名稱空間中,直接使用名字就可以了

 

總結:

導入模塊的時候 sys.modules import
使用變量的時候看的是命名空間 globals()

 

導入多個

修改demo.py

from my_module import func1,func2
func1()
func2()

執行輸出:

from the my_module.py
in func
in func2

 

盡管導入的func1,func2都屬於全局的變量了,
但是使用func2的時候要用到的變量仍然是局部的

my_module和 demo 是2個內存空間
my_module不能引用demo的變量

 

from 也支持as

from my_module import func1 as func

  

用戶可以選擇算法:

修改my_module.py的代碼

def func1():
    print('sha')

def func2():
    print('sha256')

def func3():
    print('md5')

修改demo.py,內容如下:

from my_module import func1,func2,func3
inp = input('sha or sha2 or md5>>>')
if inp ==  'sha':
    from my_module import func1 as func
elif inp ==  'sha2':
    from my_module import func2 as func
elif inp ==  'md5':
    from my_module import func3 as func

func()

執行輸出:

sha or sha2 or md5>>>sha2
sha256

 

也支持導入多行 

from my_module import (read1, 
                       read2, 
                       money)

 

導入所有

from my_module import *

 

修改my_module.py

class A:pass
a = 1
def func1():
    print('sha')

def func2():
    print('sha256')

def func3():
    print('md5')

修改demo.py

from my_module import *
print(a)
print(A)
print(func1)

執行輸出:

1
<class 'my_module.A'>
<function func1 at 0x0000023EC8749950>

 

看下面的圖

 

在my_module,里面維護了變量a,A,func1

在demo里面,也有a,A,func1。但是它實際對應的值,是my_module里面的a,A,func1

 

在my_module.py中新增一行

這樣在另外一個文件中用from my_module import *就這能導入列表中規定的兩個名字

 修改my_module.py文件,內容如下:

__all__=['a','A']
class A:pass
a = 1
def func1():
    print('sha')

def func2():
    print('sha256')

def func3():
    print('md5')

再次執行demo.py就會報錯

NameError: name 'func1' is not defined

因為func被約束了。__all__只能約束*,其他的不能約束

比如

from my_module import func1

  

總結:

from ... import ...
from 模塊名 import 名字
導入的名字直接屬於全局,但是指向模塊的名字所在的內存空間
導入的名字如果是函數或者方法,引用了全局的變量,
仍然使用模塊中的變量
導入的名字和全局的名字是一樣的,誰最后搶占到就是誰的
可以導入多個名字,用逗號分割
還可以起別名 as
from 模塊 import * 那么默認會把模塊中所有名字都導入到全局
* 和 __all__

 

今日作業:

作業1:計算文件夾中所所有文件的大小
作業2:
思考:假如有兩個模塊a,b。
我可不可以在a模塊中import b ,再在b模塊中import a?

答案:

1.

import os

def visitDir(path):
    if not os.path.isdir(path):  # 判斷是否為目錄
        print('Error: "', path, '" is not a directory or does not exist.')
        return
    else:
        global x  # 設置全局變量
        try:
            for lists in os.listdir(path):  # 列出指定目錄下的所有文件和子目錄,包括隱藏文件,並以列表方式打印
                sub_path = os.path.join(path, lists)  # 將多個路徑組合為文件名
                file_size = os.path.getsize(sub_path) # 文件大小
                x += 1  # 計算器加1
                print('No.{}\t{}\t{}字節'.format(x,sub_path,file_size))  # 輸出文件列表

                if os.path.isdir(sub_path):  # 判斷路徑是否為目錄
                    visitDir(sub_path)  # 調用自身
        except:
            pass


if __name__ == '__main__':
    x = 0  # 計數器初始值
    path = r"E:\python_script\day26\test"
    visitDir(path)  # 執行函數
    print('Total Permission Files: ', x)  # 輸出文件個數

執行輸出:

No.1 E:\python_script\day26\test\a 0字節
No.2 E:\python_script\day26\test\a\b 0字節
No.3 E:\python_script\day26\test\a\b\meow.rar 5241字節
No.4 E:\python_script\day26\test\a\b\openvpn-2.4.4.tar.gz 1390194字節
No.5 E:\python_script\day26\test\a\b\Shadowsocks-win-2.5.zip 186030字節
No.6 E:\python_script\day26\test\a\meow.rar 5241字節
No.7 E:\python_script\day26\test\a\openvpn-2.4.4.tar.gz 1390194字節
No.8 E:\python_script\day26\test\a\Shadowsocks-win-2.5.zip 186030字節
No.9 E:\python_script\day26\test\fds 0字節
No.10 E:\python_script\day26\test\fds\232 0字節
No.11 E:\python_script\day26\test\fds\232\新建 Microsoft PowerPoint 演示文稿.pptx 0字節
No.12 E:\python_script\day26\test\fds\Shadowsocks-win-2.5.zip 186030字節
No.13 E:\python_script\day26\test\meow.rar 5241字節
No.14 E:\python_script\day26\test\openvpn-2.4.4.tar.gz 1390194字節
No.15 E:\python_script\day26\test\Shadowsocks-win-2.5.zip 186030字節
Total Permission Files: 15

  

 

 
 
 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM