Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

技巧-Python #45

Open
ghost opened this issue Jan 16, 2019 · 7 comments
Open

技巧-Python #45

ghost opened this issue Jan 16, 2019 · 7 comments

Comments

@ghost
Copy link

ghost commented Jan 16, 2019

import os
if os.path.isdir(path):
    print "it's a directory"
elif os.path.isfile(path):
    print "it's a normal file"
else:
    print "it's a special file(socket,FIFO,device file)"

>>> os.path.exists('d:/assist')
 True
>>> os.path.exists('d:/assist/getTeacherList.py')
 True

os.path.getsize(path)
@ghost
Copy link
Author

ghost commented Jan 16, 2019

# 显示目录下所有文件
g = os.walk(r"e:\test")  

for path,dir_list,file_list in g:  
    for file_name in file_list:  
        print(os.path.join(path, file_name) )

# 显示所有子目录 
g = os.walk("e:\test")  

for path,dir_list,file_list in g:  
    for dir_name in dir_list:
        print(os.path.join(path, dir_name) )

@ghost
Copy link
Author

ghost commented Jan 17, 2019

  • auther: Lart
  • date: 2019-01-17
  • update: 2019-01-18 09:55:36

import os, glob, fnmatch

针对某些操作, 官方推荐这些操作

This module provides a portable way of using operating system dependent functionality.

  • If you just want to read or write a file see open()
  • if you want to manipulate paths, see the os.path module
  • if you want to read all the lines in all the files on the command line see the fileinput module
  • for creating temporary files and directories see the tempfile module
  • for high-level file and directory handling see the shutil module.

环境变量

  • os.environ
  • os.getenv(key, default=None)
# 在操作系统中定义的环境变量,全部保存在os.environ这个变量中,可以直接查看:

>>> os.environ
environ({...'LD_LIBRARY_PATH': '/usr/local/cuda-9.0/lib64:/usr/local/cuda-9.0/lib64', ..., 'LC_IDENTIFICATION': 'zh_CN.UTF-8', ...})


# 要获取某个环境变量的值,可以调用如下操作:
>>> os.environ['MANPATH']
'/home/lart/texlive/2018/texmf-dist/doc/man:/usr/local/man:'
>>> os.environ.get('MANPATH')
'/home/lart/texlive/2018/texmf-dist/doc/man:/usr/local/man:'
>>> os.environ.get('MANPATH', 'not found')
'/home/lart/texlive/2018/texmf-dist/doc/man:/usr/local/man:'
>>> os.environ.get('MAINPATH', 'not found')
'not found'
>>> os.environ('MAINPATH')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: '_Environ' object is not callable

>>> os.getenv('MANPATH')
'/home/lart/texlive/2018/texmf-dist/doc/man:/usr/local/man:'
>>> os.getenv('MAINPATH', "not found")
'not found'
# os.getenv最大的差异就在于不存在路径的时候, 不会引发异常
>>> os.getenv('MAINPATH')

系统指令

  • os.system(command)
    • 返回值只会有0(成功), 1, 2
  • os.popen(command)
    • 把执行的cmd的输出作为值返回

python调用Shell脚本,有两种方法:os.system(command)os.popen(command), 前者返回值是脚本的退出状态码, 后者的返回值是脚本执行过程中的输出内容. 实际使用时视需求情况而选择.

# 通过 os.popen() 返回的是 file read 的对象,对其进行读取 read() 的操作可以看到执行的输出。
output = os.popen('cat /proc/cpuinfo')
print(output.read())

系统信息

  • os.name
  • os.uname()
  • sys.platform(import sys)
  • os.sep
  • os.linesep
  • os.pathsep
  • os.curdir
  • os.pardir
  • os.cpu.count()
# 获取系统类型
>>> os.name
'posix'
>>> os.uname()
posix.uname_result(sysname='Linux', nodename='lart', release='4.15.0-43-generic', version='#46-Ubuntu SMP Thu Dec 6 14:45:28 UTC 2018', machine='x86_64')
>>> os.uname()[0]
'Linux'
>>> os.uname()[4]
'x86_64'
>>> import sys
>>> sys.platform
'linux'

# 获取当前路径/父路径的标识符
>>> os.curdir
'.'
>>> os.pardir
'..'
# 获取路径分隔符和换行符的表示
>>> os.sep
'/'
>>> os.linesep
'\n'
# 获取当前系统环境变量分隔符
>>> os.pathsep
':'

# 获取cpu核心数
# 此数字不等于当前进程可以使用的CPU数量。可以使用`len(os.sched_getaffinity(0))`获得可用CPU的数量
>>> os.cpu_count()
12
>>> len(os.sched_getaffinity(0))
12

文件(夹)操作

  • os.remove(path, *, dir_fd=None)

    • 移除path对应的 文件
    • 若path为文件夹, 会抛出异常OSError
  • os.rmdir(path, *, dir_fd=None)

    • 移除path对应的 文件夹
    • Only works when the directory is empty, otherwise, OSError is raised.
  • os.mkdir(path, mode=0o777, *, dir_fd=None)

    • 创建path对应的 文件夹
    • If the directory already exists, FileExistsError is raised.
  • os.removedirs(name)

    • 递归删除文件夹
    • For example, os.removedirs('foo/bar/baz') will first remove the directory 'foo/bar/baz', and then remove 'foo/bar' and 'foo' if they are empty. Raises OSError if the leaf directory could not be successfully removed
  • os.makedirs(name, mode=0o777, exist_ok=False)

    • 递归创建文件夹
    • If exist_ok is False (the default), an OSError is raised if the target directory already exists.
    • Note makedirs() will become confused if the path elements to create include pardir (eg. “..” on UNIX systems).
  • os.rename(src, dst, *, src_dir_fd=None, dst_dir_fd=None)

    • 将文件(夹)的名字从src改为dst
    • 只能对相应的文件进行重命名, 不能重命名文件的上级目录名
    • If dst is a directory, OSError will be raised. 如果src参数对应文件或目录不存在, 以及如果dst参数对应文件或目录已经存在,都会报错
    • If you want cross-platform overwriting of the destination, use replace().
  • os.renames(old, new)

    • 递归重命名文件(文件夹)
    • 既可以重命名文件, 也可以重命名文件的上级目录名
    • Note This function can fail with the new directory structure made if you lack permissions needed to remove the leaf directory or file.

路径获取

  • os.getcwd()
  • os.listdir(path='.')
  • os.scandir(path='.')
  • os.walk(top, topdown=True, onerror=None, followlinks=False)
######################################################################################
# 返回当前进程工作路径
>>> os.getcwd()
'/home/lart/md/python总结'

######################################################################################
# 返回指定path下的文件夹与文件(包含后缀名)的完整名字, 不包含'.', '..'这样的特殊目录
>>> os.listdir('.')
['converter.py', 'face++.py', 'Face++.ipynb', 'person-young-man-beard-emotions-157966.png', '.ipynb_checkpoints', '.idea', 'supervisely.py', 'facepp-python-sdk-master']

######################################################################################
# 使用内容管理器管理os.scandir迭代器, 返回的是一个`os.DirEntry`对象, 相比`os.listdir`可以获得更多的信息
# `os.DirEntry` Object yielded by scandir() to expose the file path and other file attributes of a directory entry.
# 包含如下属性与方法: `name, path, inode(), is_dir(*, follow_symlinks=True), is_file(*, follow_symlinks=True), is_symlink(), stat(*, follow_symlinks=True)`
>>> with os.scandir('.') as it:
...     for entry in it:
...         if not entry.name.startswith('.') and entry.is_file():
...             print(entry.name)
...         if entry.is_dir():
...             print(f"{entry.name}是名字")
...
converter.py
face++.py
Face++.ipynb
person-young-man-beard-emotions-157966.png
.ipynb_checkpoints是名字
.idea是名字
supervisely.py
facepp-python-sdk-master是名字

有目录:

➜  tool_scripts tree
.
├── converter.py
├── Face++.ipynb
├── facepp-python-sdk-master
│   ├── call_four_task.ipynb
│   ├── call.py
│   ├── facepp_custom.py
│   ├── imgResource
│   │   ├── demo.jpeg
│   │   ├── gray_image.png
│   │   ├── merge.jpg
│   │   ├── resultImg.jpg
│   │   ├── resultImg.png
│   │   ├── search.png
│   │   ├── segment.b64
│   │   └── segment.jpg
│   ├── PythonSDK
│   │   ├── compat.py
│   │   ├── facepp.py
│   │   ├── ImagePro.py
│   │   ├── __pycache__
│   │   │   ├── compat.cpython-36.pyc
│   │   │   ├── facepp.cpython-36.pyc
│   │   │   ├── ImagePro.cpython-36.pyc
│   │   │   └── structures.cpython-36.pyc
│   │   └── structures.py
│   ├── Python SDK demo 使用文档.pdf
│   └── README.md
├── face++.py
├── person-young-man-beard-emotions-157966.png
└── supervisely.py

4 directories, 26 files
######################################################################################
# os.walk(top, topdown=True, onerror=None, followlinks=False)
# top 是要便利的目录的地址, 为最上层的地址
# topdown 为True(默认为True),则优先遍历父目录(先把父目录里的所有文件(文件夹)遍历完, 在搜索子文件夹),否则优先遍历top的子目录 (广度优先与深度优先)
# onerror 需要一个callable对象,当walk需要异常时,会调用
# followlinks如果为True,则会遍历目录下的快捷方式(linux下是`symbolic link`)实际所指的目录(默认False)
#
# os.walk 的返回值是一个生成器(generator),也就是说不断的遍历它,来获得所有的内容。
# 每次遍历的对象都是返回的是一个三元组`(dirpath, dirnames, filenames)`
# dirpath (string)当前正在遍历的这个文件夹的本身的地址
# dirnames (list)**该文件夹中** 所有的 *子文件夹* 的名字(不包括子目录, excluding '.' and '..')
# filenames (list)**该文件夹中** 所有的 *文件* 的名字
# 注意:
#   - 名字列表中不包含完整路径, 要想得到完整的路径, 可以使用`os.path.join(dirpath, name)`.
#   - 当设定`followlinks`为True时, 若是链接指向父文件夹, 会导致无线递归, 因为`.walk()`不会关注搜索过得部分
#   - 如果传递相对路径名,请不要在`walk()`的恢复之间更改当前工作目. `walk()`从不更改当前目录, 并假定其调用者也不会

###############################################################################
# 下面使用了`topdown=True`
>>> for dirpath, dirnames, filenames in os.walk('.'):
...     print(dirpath)
...     print(dirnames)
...     print(filenames)
...
.
['.ipynb_checkpoints', '.idea', 'facepp-python-sdk-master']
['converter.py', 'face++.py', 'Face++.ipynb', 'person-young-man-beard-emotions-157966.png', 'supervisely.py']
./.ipynb_checkpoints
[]
['Face++-checkpoint.ipynb']
./.idea
[]
['misc.xml', 'modules.xml', 'workspace.xml', 'tool_scripts.iml', 'encodings.xml']
./facepp-python-sdk-master
['imgResource', 'PythonSDK', '.ipynb_checkpoints', '.idea']
['call.py', 'facepp_custom.py', 'call_four_task.ipynb', 'Python SDK demo 使用文档.pdf', 'README.md', '.gitignore']
./facepp-python-sdk-master/imgResource
[]
['demo.jpeg', 'resultImg.jpg', 'merge.jpg', 'gray_image.png', 'segment.jpg', 'search.png', 'segment.b64', 'resultImg.png']
./facepp-python-sdk-master/PythonSDK
['__pycache__']
['compat.py', 'facepp.py', 'ImagePro.py', 'structures.py']
./facepp-python-sdk-master/PythonSDK/__pycache__
[]
['compat.cpython-36.pyc', 'facepp.cpython-36.pyc', 'ImagePro.cpython-36.pyc', 'structures.cpython-36.pyc']
./facepp-python-sdk-master/.ipynb_checkpoints
[]
['call_four_task-checkpoint.ipynb']
./facepp-python-sdk-master/.idea
[]
['misc.xml', 'modules.xml', 'facepp-python-sdk-master.iml', 'workspace.xml', 'encodings.xml']

###############################################################################
# 下面使用了`topdown=False`
>>> for dirpath, dirnames, filenames in os.walk('.', topdown=False):
...     print(dirpath)
...     print(dirnames)
...     print(filenames)
...
./.ipynb_checkpoints
[]
['Face++-checkpoint.ipynb']
./.idea
[]
['misc.xml', 'modules.xml', 'workspace.xml', 'tool_scripts.iml', 'encodings.xml']
./facepp-python-sdk-master/imgResource
[]
['demo.jpeg', 'resultImg.jpg', 'merge.jpg', 'gray_image.png', 'segment.jpg', 'search.png', 'segment.b64', 'resultImg.png']
./facepp-python-sdk-master/PythonSDK/__pycache__
[]
['compat.cpython-36.pyc', 'facepp.cpython-36.pyc', 'ImagePro.cpython-36.pyc', 'structures.cpython-36.pyc']
./facepp-python-sdk-master/PythonSDK
['__pycache__']
['compat.py', 'facepp.py', 'ImagePro.py', 'structures.py']
./facepp-python-sdk-master/.ipynb_checkpoints
[]
['call_four_task-checkpoint.ipynb']
./facepp-python-sdk-master/.idea
[]
['misc.xml', 'modules.xml', 'facepp-python-sdk-master.iml', 'workspace.xml', 'encodings.xml']
./facepp-python-sdk-master
['imgResource', 'PythonSDK', '.ipynb_checkpoints', '.idea']
['call.py', 'facepp_custom.py', 'call_four_task.ipynb', 'Python SDK demo 使用文档.pdf', 'README.md', '.gitignore']
.
['.ipynb_checkpoints', '.idea', 'facepp-python-sdk-master']
['converter.py', 'face++.py', 'Face++.ipynb', 'person-young-man-beard-emotions-157966.png', 'supervisely.py']

os.path

路径显示

  • os.path.abspath(path)

    • 返回path对应的绝对路径
  • os.path.commonpath(paths)

  • os.path.commonprefix(list)

>>> os.path.commonprefix(['/usr/lib', '/usr/local/lib'])
'/usr/l'
>>> os.path.commonpath(['/usr/lib', '/usr/local/lib'])
'/usr'
  • os.path.dirname(path)
    • 返回path对应的倒数第二级目录
>>> path = '/home/lart/Datasets/tool_scripts'
>>> os.path.dirname(path)
'/home/lart/Datasets'
>>> path = '/home/lart/Datasets/tool_scripts/converter.py'
>>> os.path.dirname(path)
'/home/lart/Datasets/tool_scripts'
  • os.path.exists(path)
'/home/lart/Datasets'
>>> os.path.exists(path)
True
>>> path = '/home/lart/Datasets/tool_scripts/converter.py'
>>> os.path.exists(path)
True

路径判断

  • os.path.expanduser(path)
    • 替换path中的~为用户目录(HOME)实际值
  • os.path.expandvars(path)
    • 替换$name or ${name}为environment variable name对应的实际值
>>> path = '~/Datasets/tool_scripts/converter.py'
>>> os.path.expanduser(path)
'/home/lart/Datasets/tool_scripts/converter.py'
>>> path = '~/Datasets/tool_scripts'
>>> os.path.expanduser(path)
'/home/lart/Datasets/tool_scripts'

路径时间

  • os.path.getatime(path)
    • 返回最后一次访问path的时间
  • os.path.getmtime(path)
    • 返回最后一次修改path的时间
  • os.path.getctime(path)
    • 返回path对应的的ctime
    • 在某些系统(如Unix)上是最后一次元数据更改的时间,而在其他系统(如Windows)上则是路径的创建时间
>>> path = '/home/lart/Datasets/tool_scripts'
>>> os.path.getctime(path)
1547694633.120985
>>> os.path.getctime(path + '/converter.py')
1546766886.501085

路径体积

  • os.path.getsize(path)
    • 返回path对应的体积
>>> path = '/home/lart/Datasets/tool_scripts'
>>> os.path.getsize(path)
4096
>>> os.path.getsize(path + '/converter.py')
857

路径规范

  • os.path.isabs(path)

    • path是否为绝对路径
  • os.path.isfile(path)

  • os.path.isdir(path)

  • os.path.islink(path)

    • 如名
  • os.path.join(path, *paths)

    • 使用系统对应的分隔符拼接路径
    • 对于Windows: Note that since there is a current directory for each drive, os.path.join("c:", "foo") represents a path relative to the current directory on drive C: (c:foo), not c:\foo.
  • os.path.normcase(path)

    • 规范化路径名的大小写。
    • 在Unix和Mac OS X上,这将返回路径不变; 在不区分大小写的文件系统上,它将路径转换为小写。在Windows上,它还将正斜杠转换为反斜杠
  • os.path.normpath(path)

    • 通过折叠冗余分隔符和上级引用来规范化路径名,以便A//BA/B/A/./BA/foo/../B都变为A/B.
    • 此字符串操作可能会更改包含符号链接的路径的含义
    • 在Windows上,它将正斜杠转换为反斜杠
    • 要规范化大小写,请使用normcase()
  • os.path.realpath(path)

    • 返回指定文件名的规范路径,消除路径中遇到的任何符号链接(如果操作系统支持它们)
  • os.path.samefile(path1, path2)

    • 如果两个路径名参数都引用相同的文件或目录,则返回True
  • os.path.sameopenfile(fp1, fp2)

    • 如果文件描述符fp1和fp2引用同一文件,则返回True
  • os.path.split(path)

    • 将路径名路径拆分为一对(head, tail),其中tail是最后一个路径名组件,head是指向该路径的所有内容, tail永远不会有斜线; 如果path以斜线结尾,则tail将为空; 如果路径中没有斜杠,则head将为空
    • 如果path为空,则head和tail都为空
    • 尾部斜杠从head剥离,除非它是root(仅一个或多个斜杠)
    • 在所有情况下,join(head, tail)返回与path相同位置的路径(但字符串可能不同).
  • os.path.splitdrive(path)

    • 将路径名路径拆分为一对(drive, tail),其中drive是挂载点或空字符串. 在不使用驱动器规格的系统上,drive将始终为空字符串
    • 在所有情况下,drive + tail将与path相同。
  • os.path.splitext(path)

    • 将路径名路径拆分为一对(root, ext), 使得root + ext == path,ext为空或以.开头,最多包含一个句点. basename的前导.被忽略
    • splitext('.cshrc')返回('.cshrc','')
  • os.path.supports_unicode_filenames

    • 如果可以将任意Unicode字符串用作文件名(在文件系统强加的限制内),则为True。

glob

glob模块根据Unix shell使用的规则查找与指定模式匹配的所有路径名,尽管结果以任意顺序返回。

实现了:

  • * 表示匹配0到多个字符
  • 表示匹配一个字符
  • [] 表示匹配括号里表示的字符范围
    • [exp] 匹配指定范围内的字符,如:[1-9]匹配1至9范围内的字符, 破折號(-)表示一個範圍, 上面的範圍也可直接用[0123456789]來表示
    • [!exp] 匹配不在指定范围内的字符
    • 对于文字匹配,将元字符包装在括号中。例如,'[?]'匹配字符'?'

glob中模式規則不是正則表達式, 而是, 符合標準Uinx路徑擴展規則. 但是Shell變量名和符號(~)是不被擴充的, 只有一些特殊的字符: 兩個不同的通配符和字母範圍被支持(见上). 对于~符和shell变量扩展,请使用os.path.expanduser()os.path.expandvars(0). 模塊規則適合於文檔名的片段(以/為分隔, 也就是只能匹配//之间的文本), 但模式中的路徑可以是相對或者絕對路徑.

这是通过一致地使用os.scandir()fnmatch.fnmatch()函数来完成的,而不是通过实际调用子shell。请注意,与fnmatch.fnmatch()不同,glob将以点(.)开头的文件名视为特殊情况, 通配符不会进行匹配. 可见后面的例子.

  • glob.glob(pathname, *, recursive=False)
    • 返回可能为空的(无序的, 可以借助sorted()排序)匹配路径名字列表, 这个pathname必须是包含路径规范的字符串
    • 如果recursivetrue,则模式**匹配任何文件以及零个或多个目录和子目录, 如果模式后跟os.sep,则只有目录和子目录匹配
    • 注意在大型目录树中使用**模式可能会消耗过多的时间。
  • glob.iglob(pathname, *, recursive=False)
    • 功能同上, 只是返回一个迭代器, 避免了同时的大量存储
>>> import glob
>>> path
'/home/lart/Datasets/tool_scripts'
>>> glob.iglob(path + '/*')
<generator object _iglob at 0x7fdca3773930>
# 这里只返回下一级
>>> glob.glob(path + '/*', recursive=True)
['/home/lart/Datasets/tool_scripts/converter.py', '/home/lart/Datasets/tool_scripts/face++.py', '/home/lart/Datasets/tool_scripts/Face++.ipynb', '/home/lart/Datasets/tool_scripts/person-young-man-beard-emotions-157966.png', '/home/lart/Datasets/tool_scripts/supervisely.py', '/home/lart/Datasets/tool_scripts/facepp-python-sdk-master']
# 这里会遍历所有的子目录和文件
>>> glob.glob(path + '/**', recursive=True)
['/home/lart/Datasets/tool_scripts/', '/home/lart/Datasets/tool_scripts/converter.py', '/home/lart/Datasets/tool_scripts/face++.py', '/home/lart/Datasets/tool_scripts/Face++.ipynb', '/home/lart/Datasets/tool_scripts/person-young-man-beard-emotions-157966.png', '/home/lart/Datasets/tool_scripts/supervisely.py', '/home/lart/Datasets/tool_scripts/facepp-python-sdk-master', '/home/lart/Datasets/tool_scripts/facepp-python-sdk-master/call.py', '/home/lart/Datasets/tool_scripts/facepp-python-sdk-master/imgResource', '/home/lart/Datasets/tool_scripts/facepp-python-sdk-master/imgResource/demo.jpeg', '/home/lart/Datasets/tool_scripts/facepp-python-sdk-master/imgResource/resultImg.jpg', '/home/lart/Datasets/tool_scripts/facepp-python-sdk-master/imgResource/merge.jpg', '/home/lart/Datasets/tool_scripts/facepp-python-sdk-master/imgResource/gray_image.png', '/home/lart/Datasets/tool_scripts/facepp-python-sdk-master/imgResource/segment.jpg', '/home/lart/Datasets/tool_scripts/facepp-python-sdk-master/imgResource/search.png', '/home/lart/Datasets/tool_scripts/facepp-python-sdk-master/imgResource/segment.b64', '/home/lart/Datasets/tool_scripts/facepp-python-sdk-master/imgResource/resultImg.png', '/home/lart/Datasets/tool_scripts/facepp-python-sdk-master/PythonSDK', '/home/lart/Datasets/tool_scripts/facepp-python-sdk-master/PythonSDK/compat.py', '/home/lart/Datasets/tool_scripts/facepp-python-sdk-master/PythonSDK/facepp.py', '/home/lart/Datasets/tool_scripts/facepp-python-sdk-master/PythonSDK/__pycache__', '/home/lart/Datasets/tool_scripts/facepp-python-sdk-master/PythonSDK/__pycache__/compat.cpython-36.pyc', '/home/lart/Datasets/tool_scripts/facepp-python-sdk-master/PythonSDK/__pycache__/facepp.cpython-36.pyc', '/home/lart/Datasets/tool_scripts/facepp-python-sdk-master/PythonSDK/__pycache__/ImagePro.cpython-36.pyc', '/home/lart/Datasets/tool_scripts/facepp-python-sdk-master/PythonSDK/__pycache__/structures.cpython-36.pyc', '/home/lart/Datasets/tool_scripts/facepp-python-sdk-master/PythonSDK/ImagePro.py', '/home/lart/Datasets/tool_scripts/facepp-python-sdk-master/PythonSDK/structures.py', '/home/lart/Datasets/tool_scripts/facepp-python-sdk-master/facepp_custom.py','/home/lart/Datasets/tool_scripts/facepp-python-sdk-master/call_four_task.ipynb', '/home/lart/Datasets/tool_scripts/facepp-python-sdk-master/Python SDK demo 使用文档.pdf', '/home/lart/Datasets/tool_scripts/facepp-python-sdk-master/README.md']


>>> glob.glob('./[0-9].*')
['./1.gif', './2.txt']
>>> glob.glob('*.gif')
['1.gif', 'card.gif']
>>> glob.glob('?.gif')
['1.gif']
>>> glob.glob('**/*.txt', recursive=True)
['2.txt', 'sub/3.txt']
>>> glob.glob('./**/', recursive=True)
['./', './sub/']

If the directory contains files starting with . they won’t be matched by default. 需要在匹配路径名字上补上符号.

For example, consider a directory containing card.gif and .card.gif:

>>>
>>> import glob
>>> glob.glob('*.gif')
['card.gif']
>>> glob.glob('.c*')
['.card.gif']
  • glob.escape(pathname)
    • 轉義所有的特殊字符('?','*'和'['])
    • 如果想匹配任意可能包含特殊字符的字符串,這將非常有用。drive/UNC的sharepoints中的特殊字符不會轉義,例如在Windows系統上escape('//?/c:/Quo vadis?.txt')將返回'//?/c:/Quo vadis[?].txt'.
    • 每個特殊字符通過構建包含單個條目的字符範圍來轉義, 例如,[?]便是字符?的转义
# https://hk.saowen.com/a/83de58e8a7e060d8ace69c912cbd209948d6c4fe533aa2746201d96a1b45a8bf
import glob

specials = '?*['

for char in specials:
    pattern = 'dir/*' + glob.escape(char) + '.txt'
    print('Searching for:  {!r}'.format(pattern))
    for name in sorted(glob.glob(pattern)):
        print(name)
    print()

# 输出
Searching for:  'dir/*[?].txt'
dir/file?.txt

Searching for:  'dir/*[*].txt'
dir/file*.txt

Searching for:  'dir/*[[].txt'
dir/file[.txt
# https://www.jianshu.com/p/b1f24d56d73b
>>> glob.escape('./**.?.*.[a-z]')
'./[*][*].[?].[*].[[]a-z]'

fnmatch

此模块提供对Unix shell样式通配符的支持,这些通配符与正则表达式(在re模块中记录)不同。shell样式通配符中使用的特殊字符是:

  • * 表示匹配0到多个字符
  • 表示匹配一个字符
  • [] 表示匹配括号里表示的字符范围
    • [exp] 匹配指定范围内的字符,如:[1-9]匹配1至9范围内的字符, 破折號(-)表示一個範圍, 上面的範圍也可直接用[0123456789]來表示
    • [!exp] 匹配不在指定范围内的字符
    • 对于文字匹配,将元字符包装在括号中。例如,'[?]'匹配字符'?'

请注意:

  • 文件名分隔符(Unix上的/)对于此模块并不是特殊字符。与glob模块略有不同
  • 同样,以.开头的文件名对于此模块并不是特殊字符,并且可用*?匹配

主要的方法:

  • fnmatch.fnmatch(filename, pattern)
    • 测试是否filename字符串可以匹配模式pattern, 返回True或False
    • 这两个参数都使用os.path.normcase()进行大小写规范化。fnmatchcase()可用于执行区分大小写的比较,无论这是否是操作系统的标准。
  • fnmatch.fnmatchcase(filename, pattern)
    • 比较区分大小写,不使用os.path.normcase()
  • fnmatch.filter(names, pattern)
    • 返回与pattern匹配的名称列表的子集。它与[n for n in names if fnmatch(n, pattern)]相同,但实现更有效。
  • fnmatch.translate(pattern)
    • 返回转换为正则表达式的shell样式模式,以便与re.match()一起使用。

对于目录:

>>> print(os.popen('tree -a -L 2').read())
.
├── converter.py
├── Face++.ipynb
├── facepp-python-sdk-master
│   ├── call_four_task.ipynb
│   ├── call.py
│   ├── facepp_custom.py
│   ├── .gitignore
│   ├── .idea
│   ├── imgResource
│   ├── .ipynb_checkpoints
│   ├── PythonSDK
│   ├── Python SDK demo 使用文档.pdf
│   └── README.md
├── face++.py
├── .idea
│   ├── encodings.xml
│   ├── misc.xml
│   ├── modules.xml
│   ├── tool_scripts.iml
│   └── workspace.xml
├── .ipynb_checkpoints
│   └── Face++-checkpoint.ipynb
├── person-young-man-beard-emotions-157966.png
├── supervisely.py
└── .test

从下面的测试可以看出来, 实际上, glob应该更为常用一些, fnmatch模块不会忽略.开头的文件(夹), 这有时候会造成不必要的麻烦, 因大多数时候, 是不会需要搜索这些文件夹的.

>>> import fnmatch
>>> for file in os.listdir('.'):
...     if fnmatch.fnmatch(file, '*'):
...         print(file)
...
converter.py
face++.py
.test
Face++.ipynb
person-young-man-beard-emotions-157966.png
.ipynb_checkpoints
.idea
supervisely.py
facepp-python-sdk-master

>>> glob.glob('./*')
['./converter.py', './face++.py', './Face++.ipynb', './person-young-man-beard-emotions-157966.png', './supervisely.py', './facepp-python-sdk-master']
>>> import fnmatch, re
>>>
>>> regex = fnmatch.translate('*.txt')
>>> regex
'(?s:.*\\.txt)\\Z'
>>> reobj = re.compile(regex)
>>> reobj.match('foobar.txt')
<re.Match object; span=(0, 10), match='foobar.txt'>

参考链接

@lartpang lartpang changed the title 技巧-python 技巧-Python Jan 17, 2019
@lartpang lartpang pinned this issue Jan 17, 2019
@ghost
Copy link
Author

ghost commented Feb 28, 2019

numpy实现的onehot编码

def encode_onehot(labels):
    return (np.unique(labels) == labels[:]).astype(np.integer)

@ghost
Copy link
Author

ghost commented Mar 10, 2019

多进程处理

import argparse
import os
import time
from multiprocessing import Pool

import numpy as np
import torch
from PIL import Image
from torch.autograd import Variable
from torch.backends import cudnn
from torch.utils.data import DataLoader
from torchvision import transforms
from tqdm import tqdm

from datasets_test import ImageFolder
from misc import check_mkdir
from model_R2 import R3Net

begin = time.time()

parser = argparse.ArgumentParser(description='美少女战士 ==>> 开始处理图像')
parser.add_argument('--data_dir', type=str, default='/home/lart/Datasets/ECSSD',
                    help='测试数据文件夹')
args = parser.parse_args()

torch.manual_seed(2019)
torch.cuda.set_device(0)
cudnn.benchmark = True

img_transform = transforms.Compose([
    transforms.Resize((480, 480)),
    transforms.ToTensor(),
    transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
])

to_pil = transforms.ToPILImage()

train_set = ImageFolder(args.data_dir,
                        None,
                        img_transform)
train_loader = DataLoader(train_set,
                          batch_size=16,
                          num_workers=8,
                          shuffle=False,
                          pin_memory=True)

# 65.92232346534729
pth_path = './pth'
snapshot = '32650'
save_path = './segmentation_result'

# 使用保存好的已经训练好的模型来进行测试, 具体使用哪个, 由参数'sanpshot'确定
print('载入训练好的模型')
net = R3Net().cuda()
net.load_state_dict(torch.load(os.path.join(pth_path, snapshot + '.pth')))
net.eval()

mid_1 = time.time() - begin

############################# 以上为公用部分

with torch.no_grad():
    # img_path = os.path.join(data_dir, 'image_test_640')
    check_mkdir(save_path)
    for data in tqdm(train_loader):
        inputs, img_paths, w, h = data
        batch_size = inputs.size(0)
        img_var = Variable(inputs).cuda()
        prediction = net(img_var)

        for i_item in range(batch_size):
            img_name = (img_paths[i_item].split(os.sep)[-1]).split('.')[0]
            pre_cpu = prediction[i_item].cpu()
            pre_cpu = to_pil(pre_cpu)
            pre_cpu = pre_cpu.resize((w[i_item], h[i_item]), Image.BILINEAR)
            out = np.array(pre_cpu)
            out[out >= 211] = 255  # 找出来的
            out[out < 255] = 0
            Image.fromarray(out).save(
                os.path.join(save_path, img_name + '.png'))

mid_2 = time.time()
print("原始计时", mid_2 - begin)

# del inputs, img_paths, w, h, img_name
# -----------------------------------------------------------------------------

# pool.map 48s
# pool.apply_async 43s

def img_resize(pre_cpu, w, h, img_name):
    pre_cpu = to_pil(pre_cpu)
    pre_cpu = pre_cpu.resize((w, h), Image.BILINEAR)
    pre_cpu = np.array(pre_cpu)
    out = np.zeros_like(pre_cpu)
    out[out >= 211] = 255  # 找出来的
    Image.fromarray(out).save(
        os.path.join(save_path, img_name + '.png'))


pools_num = 8
pool = Pool(pools_num)
with torch.no_grad():
    check_mkdir(save_path)

    for data in tqdm(train_loader):
        inputs, img_paths, w, h = data
        batch_size = inputs.size(0)
        img_var = inputs.cuda()
        prediction = net(img_var)
        pre_cpu = np.array(prediction.cpu()).astype('uint8')

        # iter_item = iter([[pre_cpu[i], w[i], h[i], img_names[i]]
        #                   for i in range(batch_size)])
        # pool.map(img_resize, iter_item)

        for i_item in range(batch_size):
            img_name = (img_paths[i_item].split(os.sep)[-1]).split('.')[0]
            pool.apply_async(
                img_resize,
                args=(pre_cpu[i_item], w[i_item], h[i_item], img_name))

pool.close()
pool.join()

end = time.time()

################################## 以下为公用部分
print("多进程计时", end - mid_2 + mid_1, end - begin)

# 要比to_pil慢
# pre_cpu = np.array(
#     prediction[i].squeeze(0).cpu()).astype('uint8')
# pre_cpu = pre_cpu[:, :, np.newaxis]
# pre_cpu = np.repeat(pre_cpu, 3, axis=2)
# pre_cpu = Image.fromarray(pre_cpu)
# print(prediction.type(), pre_cpu.type())

@ghost
Copy link
Author

ghost commented Mar 26, 2019

图像相关python库

  • Numpy:主要作为图像数据的中转
  • Skimage:速度较慢,主要是caffe测试的时候默认的caffe.io.load使用,不建议使用(Skimage,读取RGB,通道HWC,范围[0,1])
  • 主要的图像处理包:
    • CV2:opencv的python版本,应用较广
    • PIL:Python自带的图像处理库,但功能较简单
    • Pillow: 出发点在于PIL只支持python2.7,添加了一些新特性
    • Pillow-SIMD:Pillow增强版本,约有5倍的增益,比CV2还要快;安装方法:
       $ pip uninstall -y pillow 
       $ CC="cc -mavx2" pip install -U --force-reinstall pillow-simd
    • Matplotlib:一般使用matplot.pyplot方法进行画图;

图像处理

Numpy

Numpy对多维矩阵A的操作一般有:

  • A.shape #HWC
  • type(A) #numpy.array
  • A.dtype() #uint8, float…
  • np.min(A), np.max(A) #最值

CV2

  • 读取BGR,通道HWC,范围[0,255] ,类型uint8;
  • 图像类型numpy.ndarray;

PIL,Pillow, Pillow-SIMD

  • 读取RGB,通道HWC,范围[0,255],类型uint8;
  • 图像类型PngImageFile (np.array, Image.fromarray直接与numpy互相转换)
  • 有.mode方法---rgb信息

Matplotlib

  • 读取RGB,通道HWC,范围[0,1] ,类型float;
  • 图像类型numpy.ndarray

Skimage

  • 读取RGB,通道HWC,范围[0,255],类型uint8;
  • 图像类型numpy.ndarray
  • 有.mode方法---rgb信息
  • 比较特殊,读取的时候image= io.imread('test.jpg',as_grey=False);
  • 彩图是uint8,[0,255];灰度图float,[0,1];
  • 彩图resize变成float,[0,1];
  • 较混乱,不适用。。。

读取

CV2

  • 默认读取为三通道彩图,可通过参数更改为单通道灰度图
    • img = cv2.imread('examples.png')
    • img_gray = cv2.imread('examples.png', 0)

PIL,Pillow, Pillow-SIMD

img = Image.open('examples.png')

Matplotlib

img = plt.imread('examples.png')

显示

Matplotlib

# 最主要目的是用来绘图: 将numpy数组格式的RGB图像显示;float类型的图像,范围0-1;如果是uint8图像,范围是0-255;
img = plt.imread('examples.png')
plt.imshow(img)
plt.show()

CV2

img = cv2.imread('examples.png')
plt.imshow(img[..., -1::-1]) # 因为opencv读取进来的是bgr顺序,而imshow需要的是rgb顺序,因此需要先反过来,也可以plt.imshow(img[:,:,::-1])
plt.show()

PIL

#可直接打开
plt.imshow(Image.open('examples.png')) # 实际上plt.imshow可以直接显示PIL格式图像
plt.show()
#转换为需要的numpy格式打开
img_gray = img.convert('L') #转换成灰度图像
img = np.array(img)
img_gray = np.array(img_gray)
plt.imshow(img) # or plt.imshow(img / 255.0)5
plt.show()
plt.imshow(img_gray, cmap=plt.gray()) # 显示灰度图要设置cmap参数
plt.show()

转换

主要是通过numpy的transpose操作,修正RGB,BGR;

例如:

  • a是rgb图像,那么 a[::-1],a[:,::-1],a[:,:,::-1]分别是X轴的镜像,Y轴的镜像,BGR转换为RGB;

opencv相关图像操作

img_gray = cv2.cvtColor(img,
cv2.COLOR_BGR2GRAY) # BGR转灰度

img_bgr = cv2.cvtColor(img_gray,
cv2.COLOR_GRAY2BGR) # 灰度转BRG

img_rgb = cv2.cvtColor(img_gray,
cv2.COLOR_GRAY2RGB) # 灰度转RGB

b,g,r = cv2.split(img) #bgr图像分离三个通道
img2 = cv2.merge([r,g,b]) #merge成rgb图像

### PIL相关图像操作

```python
img = Image.open('examples.png')
img_gray = image.convert(‘L’)
img_color = img_gray.convert(‘RGB’)

### PIL与numpy格式转换操作

```python
numpy.asarray()
Image.fromarray()

如果是pil转opencv,记得需要通过copy命令得到的才可以进行cv2操作,不然会有bug。切记.

尺寸

# PIL类型,尺寸信息,通过.size方法,得到WH
print image.size #width height
# 同样进行resize操作,顺序也是wh;
img2_resize = img2.resize((960,540))
img2_resize.save('test1.jpg')
# 而如果使用cv2操作,顺序也是wh;
img3_resize = cv2.resize(img3, (960,540))
cv2.imwrite('test2.jpg', img3_resize)
# 但如果放在numpy里面,调用shape方法,得到的是HWC;

保存

PIL

#直接save方法
img = Image.open('examples.png')
img.save('examples2.png')
img_gray = img.convert('L')
img_gray.save('examples_gray.png') # 不管是灰度还是彩色,直接用save函数保存就可以,但注意,只有PIL格式的图片能够用save函数

CV2

import cv2
img = cv2.imread('examples.png') # 这是BGR图片
cv2.imwrite('examples2.png', img) # 这里也应该用BGR图片保存,这里要非常注意,因为用pylab或PIL读入的图片都是RGB的,如果要用opencv存图片就必须做一个转换
img_gray = cv2.cvtColor(img,
cv2.COLOR_BGR2GRAY)
cv2.imwrite('examples_gray.png', img_gray)

@ghost
Copy link
Author

ghost commented Mar 28, 2019

类的属性与方法

class pub():
    _name = 'protected类型的变量'
    __info = '私有类型的变量'
    def _func(self):
        print("这是一个protected类型的方法")
    def __func2(self):
        print('这是一个私有类型的方法')
    def get(self):
        return(self.__info)

注意: 这里并没有真正意义上定义protected和私有方法, 如下文所述:

https://segmentfault.com/a/1190000002611411

@lartpang
Copy link
Owner

python的模块路径问题

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant