https://www.cnblogs.com/MnCu8261/p/5494807.html#undefined
python學(xué)習(xí)筆記-Day7(configparser模塊前计、shutil主守、壓縮與解壓模塊、subprocess)
http://www.mamicode.com/info-detail-1408907.html
shutil
-- --High-level file operations? 高級的文件操作模塊氮墨。
os模塊提供了對目錄或者文件的新建/刪除/查看文件屬性,還提供了對文件以及目錄的路徑操作。比如說:絕對路徑,父目錄……? 但是辨图,os文件的操作還應(yīng)該包含移動 復(fù)制? 打包 壓縮 解壓等操作,這些os模塊都沒有提供肢藐。
而本章所講的shutil則就是對os中文件操作的補(bǔ)充故河。--移動 復(fù)制? 打包 壓縮 解壓,
shutil功能:
1? shutil.copyfileobj(fsrc, fdst[, length=16*1024])? ? #copy文件內(nèi)容到另一個文件吆豹,可以copy指定大小的內(nèi)容
#先來看看其源代碼鱼的。defcopyfileobj(fsrc, fdst, length=16*1024):"""copy data from file-like object fsrc to file-like object fdst"""while1:
buf=fsrc.read(length)ifnotbuf:breakfdst.write(buf)#注意! 在其中fsrc瞻讽,fdst都是文件對象鸳吸,都需要打開后才能進(jìn)行復(fù)制操作importshutil
f1=open('name','r')
f2=open('name_copy','w+')
shutil.copyfileobj(f1,f2,length=16*1024)
2? shutil.copyfile(src,dst)?? #copy文件內(nèi)容,是不是感覺上面的文件復(fù)制很麻煩速勇?還需要自己手動用open函數(shù)打開文件晌砾,在這里就不需要了,事實(shí)上烦磁,copyfile調(diào)用了copyfileobj
defcopyfile(src, dst, *, follow_symlinks=True):"""Copy data from src to dst.
If follow_symlinks is not set and src is a symbolic link, a new
symlink will be created instead of copying the file it points to."""if_samefile(src, dst):raiseSameFileError("{!r} and {!r} are the same file".format(src, dst))forfnin[src, dst]:try:
st=os.stat(fn)exceptOSError:#File most likely does not existpasselse:#XXX What about other special files? (sockets, devices...)ifstat.S_ISFIFO(st.st_mode):raiseSpecialFileError("`%s` is a named pipe"%fn)ifnotfollow_symlinksandos.path.islink(src):
os.symlink(os.readlink(src), dst)else:
with open(src,'rb') as fsrc:
with open(dst,'wb') as fdst:
copyfileobj(fsrc, fdst)returndst
shutil.copyfile('name','name_copy_2')#一句就可以實(shí)現(xiàn)復(fù)制文件內(nèi)容
3? shutil.copymode(src,dst)?? #僅copy權(quán)限养匈,不更改文件內(nèi)容,組和用戶都伪。
defcopymode(src, dst, *, follow_symlinks=True):"""Copy mode bits from src to dst.
If follow_symlinks is not set, symlinks aren't followed if and only
if both `src` and `dst` are symlinks.? If `lchmod` isn't available
(e.g. Linux) this method does nothing."""ifnotfollow_symlinksandos.path.islink(src)andos.path.islink(dst):ifhasattr(os,'lchmod'):
stat_func, chmod_func=os.lstat, os.lchmodelse:returnelifhasattr(os,'chmod'):
stat_func, chmod_func=os.stat, os.chmodelse:returnst=stat_func(src)
chmod_func(dst, stat.S_IMODE(st.st_mode))
#先看兩個文件的權(quán)限[root@slyoyo python_test]#ls -ltotal 4-rw-r--r--. 1 root root 79 May 14 05:17test1-rwxr-xr-x. 1 root root? 0 May 14 19:10test2#運(yùn)行命令>>>importshutil>>> shutil.copymode('test1','test2')#查看結(jié)果[root@slyoyo python_test]#ls -ltotal 4-rw-r--r--. 1 root root 79 May 14 05:17test1-rw-r--r--. 1 root root? 0 May 14 19:10test2#當(dāng)我們將目標(biāo)文件換為一個不存在的文件時(shí)報(bào)錯>>> shutil.copymode('test1','test3')
Traceback (most recent call last):
File"", line 1,inFile"/usr/local/python/lib/python3.4/shutil.py", line 132,incopymode
chmod_func(dst, stat.S_IMODE(st.st_mode))
FileNotFoundError: [Errno2] No such fileordirectory:'test233'
4? shutil.copystat(src,dst)??? #復(fù)制所有的狀態(tài)信息呕乎,包括權(quán)限,組陨晶,用戶猬仁,時(shí)間等
defcopystat(src, dst, *, follow_symlinks=True):"""Copy all stat info (mode bits, atime, mtime, flags) from src to dst.
If the optional flag `follow_symlinks` is not set, symlinks aren't followed if and
only if both `src` and `dst` are symlinks."""def_nop(*args, ns=None, follow_symlinks=None):pass#follow symlinks (aka don't not follow symlinks)follow = follow_symlinksornot(os.path.islink(src)andos.path.islink(dst))iffollow:#use the real function if it existsdeflookup(name):returngetattr(os, name, _nop)else:#use the real function only if it exists#*and* it supports follow_symlinksdeflookup(name):
fn=getattr(os, name, _nop)iffninos.supports_follow_symlinks:returnfnreturn_nop
st= lookup("stat")(src, follow_symlinks=follow)
mode=stat.S_IMODE(st.st_mode)
lookup("utime")(dst, ns=(st.st_atime_ns, st.st_mtime_ns),
follow_symlinks=follow)try:
lookup("chmod")(dst, mode, follow_symlinks=follow)exceptNotImplementedError:#if we got a NotImplementedError, it's because#* follow_symlinks=False,#* lchown() is unavailable, and#* either#* fchownat() is unavailable or#* fchownat() doesn't implement AT_SYMLINK_NOFOLLOW.#(it returned ENOSUP.)#therefore we're out of options--we simply cannot chown the#symlink.? give up, suppress the error.#(which is what shutil always did in this circumstance.)passifhasattr(st,'st_flags'):try:
lookup("chflags")(dst, st.st_flags, follow_symlinks=follow)exceptOSError as why:forerrin'EOPNOTSUPP','ENOTSUP':ifhasattr(errno, err)andwhy.errno ==getattr(errno, err):breakelse:raise_copyxattr(src, dst, follow_symlinks=follow)
5? shutil.copy(src,dst)?? #復(fù)制文件的內(nèi)容以及權(quán)限,先copyfile后copymode
defcopy(src, dst, *, follow_symlinks=True):"""Copy data and mode bits ("cp src dst"). Return the file's destination.
The destination may be a directory.
If follow_symlinks is false, symlinks won't be followed. This
resembles GNU's "cp -P src dst".
If source and destination are the same file, a SameFileError will be
raised."""ifos.path.isdir(dst):
dst=os.path.join(dst, os.path.basename(src))
copyfile(src, dst, follow_symlinks=follow_symlinks)
copymode(src, dst, follow_symlinks=follow_symlinks)returndst
6? shutil.copy2(src,dst)??? #復(fù)制文件的內(nèi)容以及文件的所有狀態(tài)信息先誉。先copyfile后copystat
defcopy2(src, dst, *, follow_symlinks=True):"""Copy data and all stat info ("cp -p src dst"). Return the file's
destination."
The destination may be a directory.
If follow_symlinks is false, symlinks won't be followed. This
resembles GNU's "cp -P src dst"."""ifos.path.isdir(dst):
dst=os.path.join(dst, os.path.basename(src))
copyfile(src, dst, follow_symlinks=follow_symlinks)
copystat(src, dst, follow_symlinks=follow_symlinks)returndst
7shutil.copytree(src, dst, symlinks=False, ignore=None, copy_function=copy2,ignore_dangling_symlinks=False) ? #遞歸的復(fù)制文件內(nèi)容及狀態(tài)信息
defcopytree(src, dst, symlinks=False, ignore=None, copy_function=copy2,
ignore_dangling_symlinks=False):"""Recursively copy a directory tree.
The destination directory must not already exist.
If exception(s) occur, an Error is raised with a list of reasons.
If the optional symlinks flag is true, symbolic links in the
source tree result in symbolic links in the destination tree; if
it is false, the contents of the files pointed to by symbolic
links are copied. If the file pointed by the symlink doesn't
exist, an exception will be added in the list of errors raised in
an Error exception at the end of the copy process.
You can set the optional ignore_dangling_symlinks flag to true if you
want to silence this exception. Notice that this has no effect on
platforms that don't support os.symlink.
The optional ignore argument is a callable. If given, it
is called with the `src` parameter, which is the directory
being visited by copytree(), and `names` which is the list of
`src` contents, as returned by os.listdir():
callable(src, names) -> ignored_names
Since copytree() is called recursively, the callable will be
called once for each directory that is copied. It returns a
list of names relative to the `src` directory that should
not be copied.
The optional copy_function argument is a callable that will be used
to copy each file. It will be called with the source path and the
destination path as arguments. By default, copy2() is used, but any
function that supports the same signature (like copy()) can be used."""names=os.listdir(src)ifignoreisnotNone:
ignored_names=ignore(src, names)else:
ignored_names=set()
os.makedirs(dst)
errors=[]fornameinnames:ifnameinignored_names:continuesrcname=os.path.join(src, name)
dstname=os.path.join(dst, name)try:ifos.path.islink(srcname):
linkto=os.readlink(srcname)ifsymlinks:#We can't just leave it to `copy_function` because legacy#code with a custom `copy_function` may rely on copytree#doing the right thing.os.symlink(linkto, dstname)
copystat(srcname, dstname, follow_symlinks=notsymlinks)else:#ignore dangling symlink if the flag is onifnotos.path.exists(linkto)andignore_dangling_symlinks:continue#otherwise let the copy occurs. copy2 will raise an errorifos.path.isdir(srcname):
copytree(srcname, dstname, symlinks, ignore,
copy_function)else:
copy_function(srcname, dstname)elifos.path.isdir(srcname):
copytree(srcname, dstname, symlinks, ignore, copy_function)else:#Will raise a SpecialFileError for unsupported file typescopy_function(srcname, dstname)#catch the Error from the recursive copytree so that we can#continue with other filesexceptError as err:
errors.extend(err.args[0])exceptOSError as why:
errors.append((srcname, dstname, str(why)))try:
copystat(src, dst)exceptOSError as why:#Copying file access times may fail on Windowsifgetattr(why,'winerror', None)isNone:
errors.append((src, dst, str(why)))iferrors:raiseError(errors)returndst#version vulnerable to race conditions
[root@slyoyo python_test]#tree copytree_test/copytree_test/└── test
├── test1
├── test2
└── hahaha
[root@slyoyo test]#ls -ltotal 0-rw-r--r--. 1 python python 0 May 14 19:36hahaha-rw-r--r--. 1 python python 0 May 14 19:36test1-rw-r--r--. 1 root? root? 0 May 14 19:36test2>>> shutil.copytree('copytree_test','copytree_copy')'copytree_copy'[root@slyoyo python_test]#ls -ltotal 12drwxr-xr-x. 3 root? root? 4096 May 14 19:36copytree_copy
drwxr-xr-x. 3 root? root? 4096 May 14 19:36copytree_test-rw-r--r--. 1 python python? 79 May 14 05:17test1-rw-r--r--. 1 root? root? ? ? 0 May 14 19:10test2
[root@slyoyo python_test]#tree copytree_copy/copytree_copy/└── test
├── hahaha
├── test1
└── test2
8? shutil.rmtree(path, ignore_errors=False, onerror=None)#遞歸地刪除文件
defrmtree(path, ignore_errors=False, onerror=None):"""Recursively delete a directory tree.
If ignore_errors is set, errors are ignored; otherwise, if onerror
is set, it is called to handle the error with arguments (func,
path, exc_info) where func is platform and implementation dependent;
path is the argument to that function that caused it to fail; and
exc_info is a tuple returned by sys.exc_info().? If ignore_errors
is false and onerror is None, an exception is raised."""ifignore_errors:defonerror(*args):passelifonerrorisNone:defonerror(*args):raiseif_use_fd_functions:#While the unsafe rmtree works fine on bytes, the fd based does not.ifisinstance(path, bytes):
path=os.fsdecode(path)#Note: To guard against symlink races, we use the standard#lstat()/open()/fstat() trick.try:
orig_st=os.lstat(path)exceptException:
onerror(os.lstat, path, sys.exc_info())returntry:
fd=os.open(path, os.O_RDONLY)exceptException:
onerror(os.lstat, path, sys.exc_info())returntry:ifos.path.samestat(orig_st, os.fstat(fd)):
_rmtree_safe_fd(fd, path, onerror)try:
os.rmdir(path)exceptOSError:
onerror(os.rmdir, path, sys.exc_info())else:try:#symlinks to directories are forbidden, see bug #1669raiseOSError("Cannot call rmtree on a symbolic link")exceptOSError:
onerror(os.path.islink, path, sys.exc_info())finally:
os.close(fd)else:return_rmtree_unsafe(path, onerror)#Allow introspection of whether or not the hardening against symlink#attacks is supported on the current platformrmtree.avoids_symlink_attacks = _use_fd_functions
9? shutil.move(src, dst) ?? #遞歸的移動文件
defmove(src, dst):"""Recursively move a file or directory to another location. This is
similar to the Unix "mv" command. Return the file or directory's
destination.
If the destination is a directory or a symlink to a directory, the source
is moved inside the directory. The destination path must not already
exist.
If the destination already exists but is not a directory, it may be
overwritten depending on os.rename() semantics.
If the destination is on our current filesystem, then rename() is used.
Otherwise, src is copied to the destination and then removed. Symlinks are
recreated under the new name if os.rename() fails because of cross
filesystem renames.
A lot more could be done here...? A look at a mv.c shows a lot of
the issues this implementation glosses over."""real_dst=dstifos.path.isdir(dst):if_samefile(src, dst):#We might be on a case insensitive filesystem,#perform the rename anyway.os.rename(src, dst)returnreal_dst=os.path.join(dst, _basename(src))ifos.path.exists(real_dst):raiseError("Destination path '%s' already exists"%real_dst)try:
os.rename(src, real_dst)exceptOSError:ifos.path.islink(src):
linkto=os.readlink(src)
os.symlink(linkto, real_dst)
os.unlink(src)elifos.path.isdir(src):if_destinsrc(src, dst):raiseError("Cannot move a directory '%s' into itself '%s'."%(src, dst))
copytree(src, real_dst, symlinks=True)
rmtree(src)else:
copy2(src, real_dst)
os.unlink(src)returnreal_dst
10? make_archive(base_name, format, root_dir=None, base_dir=None, verbose=0,dry_run=0, owner=None, group=None, logger=None)? #壓縮打包
defmake_archive(base_name, format, root_dir=None, base_dir=None, verbose=0,
dry_run=0, owner=None, group=None, logger=None):"""Create an archive file (eg. zip or tar).
'base_name' is the name of the file to create, minus any format-specific
extension; 'format' is the archive format: one of "zip", "tar", "bztar"
or "gztar".
'root_dir' is a directory that will be the root directory of the
archive; ie. we typically chdir into 'root_dir' before creating the
archive.? 'base_dir' is the directory where we start archiving from;
ie. 'base_dir' will be the common prefix of all files and
directories in the archive.? 'root_dir' and 'base_dir' both default
to the current directory.? Returns the name of the archive file.
'owner' and 'group' are used when creating a tar archive. By default,
uses the current owner and group."""save_cwd=os.getcwd()ifroot_dirisnotNone:ifloggerisnotNone:
logger.debug("changing into '%s'", root_dir)
base_name=os.path.abspath(base_name)ifnotdry_run:
os.chdir(root_dir)ifbase_dirisNone:
base_dir=os.curdir
kwargs= {'dry_run': dry_run,'logger': logger}try:
format_info=_ARCHIVE_FORMATS[format]exceptKeyError:raiseValueError("unknown archive format '%s'"%format)
func=format_info[0]forarg, valinformat_info[1]:
kwargs[arg]=valifformat !='zip':
kwargs['owner'] =owner
kwargs['group'] =grouptry:
filename= func(base_name, base_dir, **kwargs)finally:ifroot_dirisnotNone:ifloggerisnotNone:
logger.debug("changing back to '%s'", save_cwd)
os.chdir(save_cwd)returnfilename
base_name:??? 壓縮打包后的文件名或者路徑名
format:????????? 壓縮或者打包格式"zip", "tar", "bztar"or "gztar"
root_dir :???????? 將哪個目錄或者文件打包(也就是源文件)
>>> shutil.make_archive('tarball','gztar',root_dir='copytree_test')
[root@slyoyo python_test]#ls -ltotal 12drwxr-xr-x. 3 root? root? 4096 May 14 19:36copytree_copy
drwxr-xr-x. 3 root? root? 4096 May 14 19:36copytree_test-rw-r--r--. 1 root? root? ? ? 0 May 14 21:12tarball.tar.gz-rw-r--r--. 1 python python? 79 May 14 05:17test1-rw-r--r--. 1 root? root? ? ? 0 May 14 19:10 test2
configparser模塊
#configparser用于處理特定格式的文件湿刽,其本質(zhì)上是利用open來操作文件#下邊我們就創(chuàng)建這種特定格式配置文件,來操作以下這里模塊方法--------------test.conf----------------[section1]#configparser 會認(rèn)定以中括號括住的為一個節(jié)點(diǎn)(node)k1 = 111#節(jié)點(diǎn)下褐耳,每一行配置文件為鍵值對存在(也可以寫成 k2:123)k2 =v2
k3= 123k4=True
k10= 100[section2]
k1=v1#封裝一個對象config =configparser.ConfigParser()#獲取所有節(jié)點(diǎn)(sections方法)config.read(‘test.conf‘,encoding=‘utf-8‘)
ret= config.sections()#獲取所有使用中括號的節(jié)點(diǎn)名稱print(ret)==> [‘section1‘,‘section2‘]#section方法返回一個列表诈闺,包含所有節(jié)點(diǎn)名稱#獲取指定節(jié)點(diǎn)下所有的鍵值對(items方法)ret = config.items(‘section1‘)#獲取文件的 key = v 或 key:v 等 鍵值對print(ret)==> [(‘k1‘,‘123‘), (‘k2‘,‘v2‘), (‘k3‘,‘123‘), (‘k4‘,‘True‘), (‘k10‘,‘100‘)]#獲取指定節(jié)點(diǎn)下所有的鍵(options方法)ret = config.options(‘section1‘)print(ret)==> [‘k1‘,‘k2‘,‘k3‘,‘k4‘,‘k10‘]#獲取指定節(jié)點(diǎn)下指定key的值 (get方法)#注意,下邊強(qiáng)制轉(zhuǎn)換不成功是會報(bào)錯的ret1 = config.get(‘section1‘,‘k1‘)#獲取section節(jié)點(diǎn)下的k1鍵對應(yīng)的值ret2 = config.getint(‘section1‘,‘k3‘)#獲取section1節(jié)點(diǎn)下k3鍵對應(yīng)的值铃芦,并將該值轉(zhuǎn)換為Int類型ret3 = config.getfloat(‘section1‘,‘k3‘)#獲取section1節(jié)點(diǎn)下k3鍵對應(yīng)的值雅镊,并將該值轉(zhuǎn)換為float類型ret4 = config.getboolean(‘section1‘,‘k4‘)#獲取section1節(jié)點(diǎn)下k4鍵對應(yīng)的值襟雷,并將該值轉(zhuǎn)換為boolean類型print(ret1,ret2,ret3,ret4)==> 111 123 123.0True### 檢查、刪除仁烹、添加節(jié)點(diǎn) ####檢查節(jié)點(diǎn)(has_section方法)has_sec = config.has_section(‘section1‘)#檢查是否有section1節(jié)點(diǎn)print(has_sec)==> True#返回boolean值#添加節(jié)點(diǎn) (add_section方法)config.add_section(‘SEC_1‘)#添加SEC_1節(jié)點(diǎn)config.write(open(‘test.conf‘,‘w‘))#將修改的內(nèi)容寫入到test.conf#刪除節(jié)點(diǎn) (remove_section方法)config.remove_section(‘SEC_1‘)#刪除SEC_1節(jié)點(diǎn)config.write(open(‘test.conf‘,‘w‘))#將修改的內(nèi)容寫入到test.conf### 檢查耸弄、刪除、設(shè)置指定組內(nèi)的鍵值對 ####檢查鍵值對 (has_option方法)has_opt = config.has_option(‘section1‘,‘k1‘)#檢查section1節(jié)點(diǎn)是否有k1鍵print(has_opt)#刪除鍵值對 (remove_option方法)config.remove_option(‘section1‘,‘k1‘)#刪除section1節(jié)點(diǎn)的k1鍵對應(yīng)的鍵值對(這一行)config.write(open(‘test.conf‘,‘w‘))#將修改的內(nèi)容寫入到test.conf#設(shè)置鍵值對 (set方法)config.set(‘section1‘,‘k10‘,"123")#設(shè)置(有修改晃危,無添加)section1節(jié)點(diǎn)叙赚,k10=123config.write(open(‘test.conf‘,‘w‘))#將修改的內(nèi)容寫入到test.conf#注意,我們配置文件被讀取后僚饭,放入內(nèi)存中#我們剛剛所做的一切的增刪改,都是操作的內(nèi)存中已加載的配置文件胧砰,#并沒有對實(shí)際文件有所改變鳍鸵,所以我們需要執(zhí)行write方法寫入配置文件中
shutil
#將文件內(nèi)容拷貝到另一個文件中shutil.copyfileobj(open(‘old.xml‘,‘r‘), open(‘new.xml‘,‘w‘))#拷貝文件shutil.copyfile(‘f1.log‘,‘f2.log‘)#拷貝文件和權(quán)限shutil.copy(‘f1.log‘,‘f2.log‘)#遞歸的去拷貝文件夾,并忽略拷貝pyc結(jié)尾尉间,和tmp開頭的文件shutil.copytree(‘folder1‘,‘folder2‘, ignore=shutil.ignore_patterns(‘*.pyc‘,‘tmp*‘))#遞歸的去刪除文件shutil.rmtree(‘folder1‘)#遞歸的去移動文件偿乖,它類似mv命令,其實(shí)就是重命名哲嘲。shutil.move(‘folder1‘,‘folder3‘)
壓縮與解壓(zipfile贪薪、tarfile)
#壓縮解壓 zipimportzipfile#壓縮z = zipfile.ZipFile(‘test.zip‘,‘w‘)#創(chuàng)建一個 以寫的方式寫入test.zip? 的對象z.write(‘xml_t2.xml‘)#添加xml_t2.xml文件到test.zipz.write(‘xml_t3.xml‘)#添加xml_t3.xml文件到test.zipz.close()#解壓z = zipfile.ZipFile(‘test.zip‘,‘r‘)
z.extractall()#解壓所有zip#z.extract()? # 指定解壓單個z.close()
#壓縮解壓 tarfileimporttarfile#壓縮tar = tarfile.open(‘your.tar‘,‘w‘)#創(chuàng)建一個 以寫的方式寫入test.tar? 的對象tar.add(‘xml_t2.xml‘,arcname=‘xml2.xml‘)#添加tar,并重命名xml2.xmltar.add(‘xml_t3.xml‘,arcname=‘xml3.xml‘)
tar.close()#解壓tar = tarfile.open(‘your.tar‘,‘r‘)
tar.extractall()#解壓全部眠副,并可設(shè)置解壓地址tar.close()
subprocess
#call? 執(zhí)行命令画切,返回狀態(tài)碼ret = subprocess.call(‘dir‘, shell=True)
ret= subprocess.call([‘ipconfig‘,‘/all‘], shell=False)#shell為False,需要傳入列表#check_call 執(zhí)行命令囱怕,如果執(zhí)行狀態(tài)碼ret = subprocess.check_call([‘ipconfig‘,‘/all‘])
ret= subprocess.check_call(‘exit 1‘,shell=True)#沒有exit命令霍弹,會拋異常#check_output 執(zhí)行命令,如果狀態(tài)碼是0娃弓,則返回執(zhí)行結(jié)果典格,否則拋異常subprocess.check_output([‘echo‘,‘hello world‘])
subprocess.check_output(‘echo hello‘, shell=True)#popen 方法obj = subprocess.Popen("mkdir t3", shell=True, cwd=‘/home/dev‘,)#跳轉(zhuǎn)到/home/dev,執(zhí)行命令#popen 管道使用obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)#指定stdin台丛、stdout耍缴、stderr流obj.stdin.write("print(1)\n")#寫入print(1) 的stdin流obj.stdin.write("print(2)")
obj.stdin.close()
cmd_out= obj.stdout.read()#讀取stdout 數(shù)據(jù)obj.stdout.close()
cmd_error= obj.stderr.read()#讀取stderr數(shù)據(jù)obj.stderr.close()#popen 讀取管道另一種方法out_err_list = obj.communicate()#生成一個列表,列表包含stdout和stderr數(shù)據(jù)挽霉,是一個綜合方法print(cmd_out)print(cmd_error)