【python教程】python在影视行业中的具体应用举例

28 八月, 2014
329
3

screencapture_pythonHOME_ts

作者:周辉 联系邮箱:willzhou@heliumfx.com

Python语言特点

简单、易学
Python语言是少有的一种可以称得上即简单又功能强大的编程语言。你将惊喜地发现Python语言是多么地简单,
它注重的是如何解决问题而不是编程语言的语法和结构。

免费、开源
你可以获取Python的源代码,对其进行改进。比如Stackless Python,就是修改过的增强版本Python。
高阶语言
高阶语言的一个重要特性就是,你不用顾忌程序在内存上的分配和释放等底层细节。
跨平台、可移植性
你可以在Linux,Windows,Mac OS X和Solaris等操作系统上使用Python,不涉及硬件和系统细节的程序,一般
100%兼容。

解释性
与解释语言不同的另外一种语言就是编译语言。编译语言要生成最终可执行代码,需要通过编译器编译;而解释语
言则可以通过调用解释器直接执行所编写的代码。

面向对象
面向对象编程,即Object-Oriented Programming,是一种现代化的程序设计方法,大大增加代码的可重复利用
性。设计大型程序,必不可少。Python的面向对象实现,有别于C++和Java,它强大且简单。

可扩展性
你可以通过C++来编写核心部分,然后通过Python调用。比如Houdini的_hou.so就是C++开发的Python模块。
可嵌入性
比如Houdini和Nuke支持的Python表达式。
丰富的库
庞大的标准库,还有很多其他高质量的库,几乎应有尽有。

Python应用之流程管理篇

管理文件系统
◦ 深层次结构目录和文件的管理
◦ 用Python实现Job System及相关工具

开发Tactic、Shotgun等流程管理类软件的插件和模块
Qube!、HQueue等渲染农场队列管理工具也集成了Python
扩展MoinMoin Wiki
访问、管理数据库
XLS、CSV等表格处理
Python应用之Houdini篇
HOM – Houdini Object Module
HDA
hou.session
Shelf
Houdini的远程调用方式
◦ RunPythonStatements() 通过Javascript执行XML代码
◦ Houxmlrpc

Hython – 比如我们自己开发的灯光组用渲染命令
SOHO – Scripted Output of Houdini Objects
Houdini操作系统中的调用过程

pythonforcg1

Python应用之Nuke篇
TCL Expression
[ python {#PYTHON_STATEMENTS#} ]
Rotopaint
用Python来辅助进行Roto工作
Knobs
Toolbars ( menu.py )
init.py
Metadata
Callbacks
Rendering
nuke.execute(―Write1‖, 101, 200, 1)
如何安装Python
Ubuntu Linux 下,一般默认就安装好了;
Mac OS X 下?也默认安装好了,嘿嘿 ^_^
Windows?啥也没安装 T_T。WTF ?!

通过二进制包安装
从www.python.org去下载一个……双击……一般请安装在C盘。如C:\Python25。
通过编译安装
我没这么装过……因为需要事先安装Visual C++之类的编译器,较为麻烦
ORZ……
Hello, World开启python学习之旅
开始学习一门新的语言,首要就是掌握如何用它来打印一行‚Hello, World‛。
Simon Cozens说:‚它是编程之神的传统咒语,可以帮助你更好的学习语言。‛

#!/usr/bin/env python
# Filename: helloworld.py
# Date:
# Author:
# Usage: chmod +x helloworld.py
#./helloworld.py
print ―Hello World‖

基本类型—数

整数 – int
比如42就是一个整数

长整数 – long
‚长一点‛的整数。比如2222222222222222。

浮点数 – float
就是数学中的小数。比如4.2,4.2e-2(即0.042)。

复数 – complex
4+2j就表示复数。其中4是该复数的实部,2则是虚部。

基本类型—字符串str

使用单引号
‗Hello World‘

使用双引号
―Hello World‖

使用三引号(python特有)
‗‗‗Hello World ‘‘‘
转义符
\

自然字符串
r‘…..‘

Unicode字符串
u‘…..‘

字符串级连
‗hello‘ ‗world‘

常量与变量

在Python中常量就是值本身
比如1,‚1‛,1.1,‚1.1‛等等…

用什么存储常量?变量
变量的‚名字‛——标识符:
◦ 标识符的第一个字符必须是字母表中的字母(大写或小写)或者一个下划线‘ _’。
◦ 标识符名称的其他部分可以由字母(大写或小写)、下划线‘ _ ‘或数字(0-9)组成。
◦ 标识符名称是对大小写敏感的。例如,mysop和mySop不是同一个标识符。注意前者中的小s
和后者中的大S。
◦ 有效标识符名称的例子:
i、mySop、__name和a1b2_c3。
◦ 无效标识符名称的例子:
2things、this is spaced out和my-name。
思考?
_、_ _42、_42_、_ _42_ _、42_ _和42_,那个是正确的标识符?
哪个是错误的标识符?

Python变量使用
参考下面例子
#!/usr/bin/env python
# Filename: var_test.py
i = 42
print i
i = 42 + 1
print i
s = ‗Hello World‘
print s
s = ‗‗‗this is a long long long long
long long long line‘‘‘

Python运算符与表达式

算术运算
+加
-减
*乘
/除
** 幂
// 取整除
%取模

运算应用举例
>>> 1 + 1
2
>>> -2 – 3
-5
>>> 2 * 3
6
>>> 2 ** 3
8
>>> 8.0 / 3.0
2.6666666666666665
>>> 8.0 // 3.0
2.0
>>> 8.0 % 3.0
2.0

位运算
<< 左移
5 << 1 == 10
> 右移
5 >> 1 == ?
& 按位与
5 & 2 == 0
| 按位或
5 | 2 == 7
-(X+1)

逻辑运算
< 小于
1 True
> 大于
1>2 -> False
<= 小于等于 >= 大于等于
== 等于
1+1 == 2 -> True
!= 不等于
1+1 != 3 -> True
not 布尔非
not 1 False
and 布尔与
2>1 and 3>2 -> True
or 布尔或
22 -> True

运算符优先级表从低到高(部分)

pythonforcg2 运算符优先级
运算符优先级表决定了哪个运算符在别的运算符之前计算
可以使用圆括号改变它们的计算顺序
#!/usr/bin/env python
# Filename: simple_gray.py
# Author: Will Zhou
# Date: 2010-07-29 14:09:01
r = 0.3
g = 0.8
b = 0.6
gray = 0.3*r + 0.6*g + 0.1*b
print gray
r = g = b = gray

运算符与表达式在Nuke中应用演示

pythonforcg3

效果预览

pythonforcg4

Python控制流

if – elif – else 条件语句
#!/usr/bin/env python
# coding=utf8
# Filename: hfs_selector.py
import sys
if len(sys.argv) == 2: # 判断是否有2个参数(包括默认参数)
ver = sys.argv[1]# 将命令行获取的参数赋给变量ver
if ver == ―10.0.595:‖ # 判断ver的值是否为字符串‖10.0.595‖
print ―cd /opt/hfs10.0.595‖
print ―source houdini_setup‖
print ―cd –‖
elif ver == ―11.0.446‖: # 如果不是,则继续判断
print ―cd /opt/hfs11.0.446‖
print ―source houdini_setup‖
print ―cd –‖
else:# 否则,就干嘛……
print ―echo Sorry, there is no such version houdini‖
while 循环
#!/usr/bin/env python
# coding=utf8
# Filename: image_check.py
# Description: This code should be run in Nuke.
import os
import thread
def check():
# 如果图片不存在则继续循环
while not os.path.exists(‗d:/test.tga‘):
pass# pass在程序不具体做什么的时候很好用
# 循环退出的时候,将立刻执行下面的语句
nuke.message(‗The image is ready!‘)
thread.start_new_thread(check, ())
while 循环Nuke演示

pythonforcg5

pythonforcg6for 循环
#!/usr/bin/env python
# coding=utf8
# Filename: for.py
# Description: This code should be run in Houdini.
import hou
grid1 = hou.node(‗/obj/geo1/grid1‘) # 获取创建好的grid对象
points = grid1.geometry().points()# 返回一个点序列
for point in points:# 用 for 循环遍历序列中的各个点
print point.position() # 打印点的坐标
for 循环Houdini演示

pythonforcg7 break 和 continue 语句
break语句
是用来终止循环语句的,即哪怕循环条件没有称为False或序列还没
有被完全递归,也停止执行循环语句。
continue语句
被用来告诉Python跳过当前循环块中的剩余语句,然后继续进行下
一轮循环。
break 语句
#!/usr/bin/env python
# Filename: break.py
i=1
while i < 10: print i if i > 5:
i=i+1
break
else:
i=i+1
print ‗break‘

continue 语句
#!/usr/bin/env python
# Filename: continue.py
i=1
while i < 10: print i if i > 5:
i=i+1
continue
else:
i=i+1
print ‗continue‘
Python控制流作业
1、将 if 判断语句的代码例子,仔细的输入编辑器(如vim)中,保存
名为 hfs_selector.py 的源代码文件,然后在终端中调用python命
令执行该代码。将代码执行后的输出结果,在Linux终端执行一遍,
然后思考一下整个过程。
2、分别用while和for循环编写一个程序,程序的作用是打印出以下内
容:
pythonforcg8 第2题参考程序:
#——— while ———–#
i=1
while i<10:
print i
i = i +1
# ———- for ———– #
for i in range(1, 10):
print i

Python循环嵌套
如何利用循环嵌套,使程序做更多的事

pythonforcg9

Python函数

如何定义一个函数
#!/usr/bin/env python
# coding=utf8
# Filename: print_hello.py
#
# 函数用def关键字定义,def后面是函数名,
# 圆括号内则是函数的参数,
# 冒号后的缩进内容是函数体。
def printHelloWorld():
print ‗Hello World!‘
# 函数名为printHelloWorld,无参数
# 函数体
printHelloWorld()

带参数的函数
#!/usr/bin/env python
# coding=utf8
# Filename: name_fix.py
#
def nameFix(filename): # filename是函数nameFixing的参数
return filename.lower()# filename必须是字符串
# 字符串自带有lower、upper等函数
# 注意,这里的filename与函数内的filename是不一样的
filename = ‗WOF00101_Efx_TeST_V001‘
print ‗BEFORE:‘, filename
filename = nameFix(filename)
print ‗AFTER:‘, filename

带默认值的参数
#!/usr/bin/env python
# coding=utf8
# Filename: version_change.py
def versionChange(filename, ver=‗001‘): # ver是带有默认值的参数
‗‘‘ This function is used to change file versions‘‘‘ # 这是DocStrings
# help()函数会读取这个
oldver = filename[-3:]
filename = filename.replace(oldver, ver)
return filename
filename = ‗wof00101_efx_test_v002‘
print ‗BEFORE:‘, filename
filename = versionChange(filename)
print ‗DEFAULT:‘, filename
filename = versionChange(filename, ver=‗009‘)
print ‗NEW:‘, filename

递归函数
#!/usr/bin/env python
# coding=utf8
# Filename: remkdir.py
# Author: Will Zhou
# Description: 创建目录的时候,同时创建其父目录,即层层创建
def remkdir(folder):
import os
if os.path.exists(folder): return # 如果存在,则用return跳出
parent = os.path.dirname(folder)
remkdir(parent) # 函数递归,跳出递归之后,将执行下面的语句
if not os.path.exists(folder):
os.mkdir(folder)

应用举例
#!/usr/bin/env python
# coding=utf8
# Filename: doublesave.py
# Description: 保存hip文件的同时,备份文件至指定目录
#本代码请保存至$HOME/houdini10.0/scripts/python/doublesave.py
def doublesave(backup=r”/home/will/backup/”):
import os
import hou
hip_path = hou.getenv(‘HIP’)
backup_path = ‗/‘.join([backup, hip_path])
remkdir(backup_path) # 在backup变量指定的目录里,递归创建原hip文件的路径
filename = os.path.basename(hou.hipFile.name())
back_file = ‗/‘.join([backup_path, filename])
hou.hipFile.save(back_file)
hou.ui.displayMessage(‗Backup to %s‘ % back_file)
origFile = os.path.join(hip_path, filename)
hou.hipFile.save(origFile)

应用举例:

pythonforcg10

Python模块

from .. import .. 语句
# import 和 from…import…的区别
# 请看下面程序
import os
os.mkdir(―new_dir‖)
from os import mkdir
mkdir(―new_dir‖)
# 一般来说,应该尽量用 import,因为 from…import…会涉及到命
# 名污染(命名冲突)等问题。

模块的 __name__
#!/usr/bin/env python
# Filename: print_hello.py
# 说明:
# 1. 每个模块都有 __name__
# 2. __name__ == ‗__main__‘ 的作用是防止模块被import
# 的时候执行某些代码
# 3. 用python命令直接执行本程序的时候,
# __name__ == ‗__main__‘ 下的子语句才会被执行
#
def printHello():
print ‗Hello World‘
if __name__ == ‗__main__‘:
printHello()

如何调用自己的模块
#!/usr/bin/env python
# Filename: main.py
from print_hello import printHello
if __name__ == ‗__main__‘:
printHello()

用dir函数查看模块
# 比如自己创建的模块 print_hello
import print_hello
dir(print_hello)
# 也可以查看标准库及任何第三方的模块
import os
dir(os)

Python数据结构

list – 列表
list是处理一组有序元素的数据结构。
#!/usr/bin/env python
# Filename: list.py
#
projects = [‗WOF‘, ‗CRD‘, ‗SIX‘, ‗TCM‘, ‗BWE‘ ]
counts = len(projects)
print ―There are %d projects we‘re working in progress‖ % counts
print projects[0]
print projects[-1]
print projects[2:4] # 4为开区间,真正输出的是第2和第3这两个元素
projects.append(‗ABC‘)
print projects

tuple – 元组
元组和列表十分类似,只不过元组和字符串一样是不可变的,即你不能修改元组。
#!/usr/bin/env python
# Filename: tuple.py
#
projects = (‗WOF‘, ‗CRD‘, ‗SIX‘, ‗TCM‘, ‗BWE‘ )
counts = len(projects)
print ―There are %d projects we‘re working in progress‖ % counts
print projects[0]
print projects[2:2] # 思考下这个输出哪个元素,然后再验证是否正确
projects.append(‗ABC‘) # 错误

dict – 字典
字典类似于你通过联系人名字查找地址和联系人详细情况的地址簿,
即,我们把键(名字)和值(详细情况)联系在一起。
注意,键必须是唯一的。
#!/usr/bin/env python
# Filename: dict.py
tasks = {‗Alex‘:‘EFX‘,
‗Mark‘:‘CMP‘,
‗Boris‘:‘RnD‘,
}
print tasks.get(‗Boris‘)
print tasks[‗Boris‘]
tasks.keys()
tasks.values()
tasks.items()

引用
#!/usr/bin/env python
# coding=utf8
# Filename: reference.py
shoplist = [‘apple’, ‘mango’, ‘carrot’, ‘banana’]
mylist = shoplist # mylist是另外一个指向同shoplist所指的对象的名字
del shoplist[0]
print ‗shoplist is‘, shoplist # 两者输出一致
print ‗mylist is‘, mylist# mylist这时就是shoplist的一个引用
mylist = shoplist[:]
del mylist[0]
print ‗shoplist is‘, shoplist
print ‗mylist is‘, mylist
# 拷贝整个shoplist的切片
# 删除第一个元素
# 两者已经各有所指
# mylist不是shotlist的引用
字符串高级操作

pythonforcg11