python3与python2迭代器的写法的区别

李魔佛 发表了文章 • 0 个评论 • 1 次浏览 • 2019-06-26 11:22 • 来自相关话题

大部分相同,只是python2里面需要实现在类中实现next()方法,而python3里面需要实现__next__()方法。
 
附一个例子:
def iter_demo():

class DefineIter(object):

def __init__(self,length):
self.length = length
self.data = range(self.length)
self.index=0

def __iter__(self):
return self


def __next__(self):

if self.index >=self.length:
# return None
raise StopIteration

d = self.data[self.index]*50
self.index =self.index + 1

return d

a = DefineIter(10)
print(type(a))
for i in a:
print(i) 查看全部
大部分相同,只是python2里面需要实现在类中实现next()方法,而python3里面需要实现__next__()方法。
 
附一个例子:
def iter_demo():

class DefineIter(object):

def __init__(self,length):
self.length = length
self.data = range(self.length)
self.index=0

def __iter__(self):
return self


def __next__(self):

if self.index >=self.length:
# return None
raise StopIteration

d = self.data[self.index]*50
self.index =self.index + 1

return d

a = DefineIter(10)
print(type(a))
for i in a:
print(i)

PyCharm 快捷键快速插入当前时间

李魔佛 发表了文章 • 0 个评论 • 2 次浏览 • 2019-06-26 09:18 • 来自相关话题

个人觉得这是一个非常常用的功能,不过需要自定义实现。
 
方式
通过 Live Template 快速添加时间

步骤
1、添加一个 Template Group 命名为 Common
2、添加一个 Live Template 设置如下
Abbreviation: time
Description : current time
Template Text: $time$

Edit Variables -> Expresssion : date("yyyy-MM-dd HH:mm:ss")



3、让设置生效
Define->Everywhere

4、使用
输入 time 后 按下tab键 就能转换为当前时间了
  查看全部
个人觉得这是一个非常常用的功能,不过需要自定义实现。
 
方式
通过 Live Template 快速添加时间

步骤
1、添加一个 Template Group 命名为 Common
2、添加一个 Live Template 设置如下
Abbreviation: time
Description : current time
Template Text: $time$

Edit Variables -> Expresssion : date("yyyy-MM-dd HH:mm:ss")



3、让设置生效
Define->Everywhere

4、使用
输入 time 后 按下tab键 就能转换为当前时间了

 

conda无法在win10下用命令行切换虚拟环境

李魔佛 发表了文章 • 0 个评论 • 62 次浏览 • 2019-06-11 10:04 • 来自相关话题

虚拟环境已经安装好了
然后在PowerShell下运行activate py2,没有任何反应。(powershell是win7后面系统的增强命令行)
后来使用系统原始的cmd命令行,在运行里面敲入cmd,然后重新执行activate py2,问题得到解决了。
原因是兼容问题。 查看全部
虚拟环境已经安装好了
然后在PowerShell下运行activate py2,没有任何反应。(powershell是win7后面系统的增强命令行)
后来使用系统原始的cmd命令行,在运行里面敲入cmd,然后重新执行activate py2,问题得到解决了。
原因是兼容问题。

jupyter notebook格式的文件损坏如何修复

李魔佛 发表了文章 • 0 个评论 • 85 次浏览 • 2019-06-08 13:44 • 来自相关话题

有时候用git同步时,造成了冲突后合并,jupyter notebook的文件被插入了诸如>>>>>HEAD,ORIGIN等字符,这时候再打开jupyter notebook文件(.ipynb后缀),会无法打开。修复过程:
 
使用下面的代码:
# 拯救损坏的jupyter 文件
import re
import codecs

pattern = re.compile('"source": \[(.*?)\]\s+\},',re.S)
filename = 'tushare_usage.ipynb'
with codecs.open(filename,encoding='utf8') as f:
content = f.read()

source = pattern.findall(content)
for s in source:
t=s.replace('\\n','')
t=re.sub('"','',t)
t=re.sub('(,$)','',t)
print(t)只要把你要修复的文件替换一下就可以了。 查看全部
有时候用git同步时,造成了冲突后合并,jupyter notebook的文件被插入了诸如>>>>>HEAD,ORIGIN等字符,这时候再打开jupyter notebook文件(.ipynb后缀),会无法打开。修复过程:
 
使用下面的代码:
# 拯救损坏的jupyter 文件
import re
import codecs

pattern = re.compile('"source": \[(.*?)\]\s+\},',re.S)
filename = 'tushare_usage.ipynb'
with codecs.open(filename,encoding='utf8') as f:
content = f.read()

source = pattern.findall(content)
for s in source:
t=s.replace('\\n','')
t=re.sub('"','',t)
t=re.sub('(,$)','',t)
print(t)
只要把你要修复的文件替换一下就可以了。

python的mixin类

李魔佛 发表了文章 • 0 个评论 • 120 次浏览 • 2019-05-16 16:30 • 来自相关话题

A mixin is a limited form of multiple inheritance.
 
maxin类似多重继承的一种限制形式:
 关于Python的Mixin模式

像C或C++这类语言都支持多重继承,一个子类可以有多个父类,这样的设计常被人诟病。因为继承应该是个”is-a”关系。比如轿车类继承交通工具类,因为轿车是一个(“is-a”)交通工具。一个物品不可能是多种不同的东西,因此就不应该存在多重继承。不过有没有这种情况,一个类的确是需要继承多个类呢?

答案是有,我们还是拿交通工具来举例子,民航飞机是一种交通工具,对于土豪们来说直升机也是一种交通工具。对于这两种交通工具,它们都有一个功能是飞行,但是轿车没有。所以,我们不可能将飞行功能写在交通工具这个父类中。但是如果民航飞机和直升机都各自写自己的飞行方法,又违背了代码尽可能重用的原则(如果以后飞行工具越来越多,那会出现许多重复代码)。怎么办,那就只好让这两种飞机同时继承交通工具以及飞行器两个父类,这样就出现了多重继承。这时又违背了继承必须是”is-a”关系。这个难题该怎么破?

不同的语言给出了不同的方法,让我们先来看下Java。Java提供了接口interface功能,来实现多重继承:public abstract class Vehicle {
}

public interface Flyable {
public void fly();
}

public class FlyableImpl implements Flyable {
public void fly() {
System.out.println("I am flying");
}
}

public class Airplane extends Vehicle implements Flyable {
private flyable;

public Airplane() {
flyable = new FlyableImpl();
}

public void fly() {
flyable.fly();
}
}

现在我们的飞机同时具有了交通工具及飞行器两种属性,而且我们不需要重写飞行器中的飞行方法,同时我们没有破坏单一继承的原则。飞机就是一种交通工具,可飞行的能力是是飞机的属性,通过继承接口来获取。

回到主题,Python语言可没有接口功能,但是它可以多重继承。那Python是不是就该用多重继承来实现呢?是,也不是。说是,因为从语法上看,的确是通过多重继承实现的。说不是,因为它的继承依然遵守”is-a”关系,从含义上看依然遵循单继承的原则。这个怎么理解呢?我们还是看例子吧。
class Vehicle(object):
pass

class PlaneMixin(object):
def fly(self):
print 'I am flying'

class Airplane(Vehicle, PlaneMixin):
pass

可以看到,上面的Airplane类实现了多继承,不过它继承的第二个类我们起名为PlaneMixin,而不是Plane,这个并不影响功能,但是会告诉后来读代码的人,这个类是一个Mixin类。所以从含义上理解,Airplane只是一个Vehicle,不是一个Plane。这个Mixin,表示混入(mix-in),它告诉别人,这个类是作为功能添加到子类中,而不是作为父类,它的作用同Java中的接口。

使用Mixin类实现多重继承要非常小心
首先它必须表示某一种功能,而不是某个物品,如同Java中的Runnable,Callable等
 
其次它必须责任单一,如果有多个功能,那就写多个Mixin类然后,它不依赖于子类的实现最后,子类即便没有继承这个Mixin类,也照样可以工作,就是缺少了某个功能。(比如飞机照样可以载客,就是不能飞了^_^) 查看全部
A mixin is a limited form of multiple inheritance.
 
maxin类似多重继承的一种限制形式:
 关于Python的Mixin模式

像C或C++这类语言都支持多重继承,一个子类可以有多个父类,这样的设计常被人诟病。因为继承应该是个”is-a”关系。比如轿车类继承交通工具类,因为轿车是一个(“is-a”)交通工具。一个物品不可能是多种不同的东西,因此就不应该存在多重继承。不过有没有这种情况,一个类的确是需要继承多个类呢?

答案是有,我们还是拿交通工具来举例子,民航飞机是一种交通工具,对于土豪们来说直升机也是一种交通工具。对于这两种交通工具,它们都有一个功能是飞行,但是轿车没有。所以,我们不可能将飞行功能写在交通工具这个父类中。但是如果民航飞机和直升机都各自写自己的飞行方法,又违背了代码尽可能重用的原则(如果以后飞行工具越来越多,那会出现许多重复代码)。怎么办,那就只好让这两种飞机同时继承交通工具以及飞行器两个父类,这样就出现了多重继承。这时又违背了继承必须是”is-a”关系。这个难题该怎么破?

不同的语言给出了不同的方法,让我们先来看下Java。Java提供了接口interface功能,来实现多重继承:
public abstract class Vehicle {
}

public interface Flyable {
public void fly();
}

public class FlyableImpl implements Flyable {
public void fly() {
System.out.println("I am flying");
}
}

public class Airplane extends Vehicle implements Flyable {
private flyable;

public Airplane() {
flyable = new FlyableImpl();
}

public void fly() {
flyable.fly();
}
}


现在我们的飞机同时具有了交通工具及飞行器两种属性,而且我们不需要重写飞行器中的飞行方法,同时我们没有破坏单一继承的原则。飞机就是一种交通工具,可飞行的能力是是飞机的属性,通过继承接口来获取。

回到主题,Python语言可没有接口功能,但是它可以多重继承。那Python是不是就该用多重继承来实现呢?是,也不是。说是,因为从语法上看,的确是通过多重继承实现的。说不是,因为它的继承依然遵守”is-a”关系,从含义上看依然遵循单继承的原则。这个怎么理解呢?我们还是看例子吧。
class Vehicle(object):
pass

class PlaneMixin(object):
def fly(self):
print 'I am flying'

class Airplane(Vehicle, PlaneMixin):
pass


可以看到,上面的Airplane类实现了多继承,不过它继承的第二个类我们起名为PlaneMixin,而不是Plane,这个并不影响功能,但是会告诉后来读代码的人,这个类是一个Mixin类。所以从含义上理解,Airplane只是一个Vehicle,不是一个Plane。这个Mixin,表示混入(mix-in),它告诉别人,这个类是作为功能添加到子类中,而不是作为父类,它的作用同Java中的接口。

使用Mixin类实现多重继承要非常小心
  • 首先它必须表示某一种功能,而不是某个物品,如同Java中的Runnable,Callable等

 
  • 其次它必须责任单一,如果有多个功能,那就写多个Mixin类
  • 然后,它不依赖于子类的实现
  • 最后,子类即便没有继承这个Mixin类,也照样可以工作,就是缺少了某个功能。(比如飞机照样可以载客,就是不能飞了^_^)

python不支持多重继承中的重复继承

李魔佛 发表了文章 • 0 个评论 • 158 次浏览 • 2019-04-18 16:36 • 来自相关话题

代码如下:
class First(object):
def __init__(self):
print("first")

class Second(First):
def __init__(self):
print("second")

class Third(First,Second):
def __init__(self):
print("third")
运行代码会直接报错:
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-6-c90f7b77d3e0> in <module>()
7 print("second")
8
----> 9 class Third(First,Second):
10 def __init__(self):
11 print("third")

TypeError: Cannot create a consistent method resolution order (MRO) for bases First, Second
  查看全部
代码如下:
class First(object):
def __init__(self):
print("first")

class Second(First):
def __init__(self):
print("second")

class Third(First,Second):
def __init__(self):
print("third")

运行代码会直接报错:
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-6-c90f7b77d3e0> in <module>()
7 print("second")
8
----> 9 class Third(First,Second):
10 def __init__(self):
11 print("third")

TypeError: Cannot create a consistent method resolution order (MRO) for bases First, Second

 

gevent异步 入门教程(入坑)

李魔佛 发表了文章 • 0 个评论 • 140 次浏览 • 2019-04-18 11:37 • 来自相关话题

code1
import time
import gevent
import requests
def foo():
print('Running in foo')

r=requests.get('http://30daydo.com')
print(r.status_code)
print('Explicit context switch to foo again')

def bar():
print('Explicit context to bar')

r=requests.get('http://www.qq.com') #
print(r.status_code)
print('Implicit context switch back to bar')

start=time.time()
gevent.joinall([
gevent.spawn(foo),
gevent.spawn(bar),
])
print('time used {}'.format(time.time()-start))
上面的异步代码不起作用,因为requests阻塞了,所以用的时间和顺序执行的时间一样.
 
或者用以下代码替代:
import time
import gevent
import requests
def foo():
print('Running in foo')
time.sleep(2) # 这样子不起作用
print('Explicit context switch to foo again')

def bar():
print('Explicit context to bar')
time.sleep(2)
print('Implicit context switch back to bar')

start=time.time()
gevent.joinall([
gevent.spawn(foo),
gevent.spawn(bar),
])
print('time used {}'.format(time.time()-start))
把访问网络部分使用sleep替代,那么最后的运行时间是2+2 =4秒,并不是2秒,那么要怎样才是2秒呢,需要改成以下的代码:
 
import time
import gevent
import requests
def foo():
print('Running in foo')

gevent.sleep(2) # 通过它各自yield向对方

print('Explicit context switch to foo again')

def bar():
print('Explicit context to bar')

gevent.sleep(2)

print('Implicit context switch back to bar')

start=time.time()
gevent.joinall([
gevent.spawn(foo),
gevent.spawn(bar),
])
print('time used {}'.format(time.time()-start))
使用gevent.sleep()
这个函数才可以达到目的. 查看全部
code1
import time
import gevent
import requests
def foo():
print('Running in foo')

r=requests.get('http://30daydo.com')
print(r.status_code)
print('Explicit context switch to foo again')

def bar():
print('Explicit context to bar')

r=requests.get('http://www.qq.com') #
print(r.status_code)
print('Implicit context switch back to bar')

start=time.time()
gevent.joinall([
gevent.spawn(foo),
gevent.spawn(bar),
])
print('time used {}'.format(time.time()-start))

上面的异步代码不起作用,因为requests阻塞了,所以用的时间和顺序执行的时间一样.
 
或者用以下代码替代:
import time
import gevent
import requests
def foo():
print('Running in foo')
time.sleep(2) # 这样子不起作用
print('Explicit context switch to foo again')

def bar():
print('Explicit context to bar')
time.sleep(2)
print('Implicit context switch back to bar')

start=time.time()
gevent.joinall([
gevent.spawn(foo),
gevent.spawn(bar),
])
print('time used {}'.format(time.time()-start))

把访问网络部分使用sleep替代,那么最后的运行时间是2+2 =4秒,并不是2秒,那么要怎样才是2秒呢,需要改成以下的代码:
 
import time
import gevent
import requests
def foo():
print('Running in foo')

gevent.sleep(2) # 通过它各自yield向对方

print('Explicit context switch to foo again')

def bar():
print('Explicit context to bar')

gevent.sleep(2)

print('Implicit context switch back to bar')

start=time.time()
gevent.joinall([
gevent.spawn(foo),
gevent.spawn(bar),
])
print('time used {}'.format(time.time()-start))

使用gevent.sleep()
这个函数才可以达到目的.

python的pip安装mysqldb

李魔佛 发表了文章 • 0 个评论 • 151 次浏览 • 2019-04-16 23:51 • 来自相关话题

换一个新环境,或者在另一台服务器上运行自己的程序,最烦就是pip安装各种依赖,尤其其他机器上的python不一致(你用的是python3,服务器用的是python2),或者两个系统都不一致。 这个时候pip安装第三方库就很折腾。
 
比如mysqldb这个库,windows用python2不知道怎样才能装上。 反正这个我几年装过,现在已经忘记怎么安装了。
今天又要装一遍,为了减轻痛苦,安装anaconda,然后使用conda install mysqldb,conda会帮你把依赖都解决掉。 不然你要装一堆的VC8,VC14, 等等。
 
然后等待一下,就安装好了。 查看全部
换一个新环境,或者在另一台服务器上运行自己的程序,最烦就是pip安装各种依赖,尤其其他机器上的python不一致(你用的是python3,服务器用的是python2),或者两个系统都不一致。 这个时候pip安装第三方库就很折腾。
 
比如mysqldb这个库,windows用python2不知道怎样才能装上。 反正这个我几年装过,现在已经忘记怎么安装了。
今天又要装一遍,为了减轻痛苦,安装anaconda,然后使用conda install mysqldb,conda会帮你把依赖都解决掉。 不然你要装一堆的VC8,VC14, 等等。
 
然后等待一下,就安装好了。

最流行的版本控制软件:git 个人笔记

李魔佛 发表了文章 • 0 个评论 • 165 次浏览 • 2019-04-16 23:37 • 来自相关话题

最流行的版本控制软件:git
========================

git已经是当前最流行的版本控制软件之一了。全世界的程序员都在使用它。它出自linus大神之手,现在被用于内
核的版本控制。在最流行的代码托管软件github,你几乎可以找到所有开源项目的代码。

版块控制软件:我需要吗?
-----------------------

的确对于许多人——尤其是非程序员,他们可能不会想到已经出现了专门的版本控制的软件。但其实多人对版本控
制其实都有类似的需求,举个例子,Tom是社团的秘书处成员,他们经常需要做的事情就是写活动文档,然后不停地
改改到大家都觉得可以了。

不幸运的话,Tom可能有个文件夹叫“openSUSE活动策划",里面有这样的一堆文件”openSUSE活动策划", "活动策
划1", "活动策划2", "活动策划3", "活动策划4" ... "活动策划20" (可怜的Tom,一份文档改了不少于20次)

这种作法很有效,因为我们可能发现第5个版本的策划有问题,我们准备在第3个版本上面重新来过。但是也看到,
这个作法有些很丑陋的地方:一份文件,我们留了20个备份,而且还要注意文件名。

如果可以这样就好了:文件夹上只有一个“openSUSE活动策划",但当我需要第5个版本的时候,我来一个”给我还
原到第5个版本吧!“,然后这时候我们打开这个文件,它就是第5个版本的了。类似的,我们可以取出任意的版本


这就是版本控制。这种事情在程序里面发生的太多了,于是出现了各种版本控制软件。事实上,有些项目已经发展
到第1000+甚至更高的版本数了……

单线的工作流
------------

我们可以把我们的一个项目想象为一个仓库,然后我们可以把我们的东西塞进仓库里面,也可以把想要的东西拿出
来。而git则是仓库的管理员。下面是一个例子,希望有一个直观的印象,不求完全的理解和掌握。

```bash
mkdir myproject // 假设myproject是工作目录
cd myproject
git init // git <- (init) ,告诉仓库管理员,在当前目录初始化
echo 'Eat the banana' > file // 编辑了一个文件
git add file // 加入仓库
git commit -m 'add first file' // 提交更改
echo 'Eat the apply' > file // 修改了这个文件
git add file // 加入仓库
git commit -m 'update first file' // 再提交更改
```

这时候我们就有两个commit了,我们来看看工作日志:

```bash
git log

# 以下是输出
# commit ac1371173b4e630ddaebda3f9f5d948b36146c07
# Author: Norman Mo <LTaoist@@@>
# Date: Thu Jun 27 21:59:10 2013 +0800
#
# update first file
#
# commit 3c43cc913454f92bb4b80c56ba45e4ffaf556fc0
# Author: Norman Mo <LTaoist6@@@@>
# Date: Thu Jun 27 21:58:48 2013 +0800
#
# add first file
```

看到了,我们提交了两次。我们来看看现在file里面是什么:

```bash
cat file # 显然输出是 'Eat the apply'
# 现在,我们来拿回第一个版本的file文件
git checkout 3c43cc913454f92bb4b80c56ba45e4ffaf556fc0 -- file
cat file # 这时候就是eat banana了
```

这种工作的方式是单人使用最常见的方式,写一点代码,提交一下到仓库里面。写一点,提交到仓库里面。然后出
问题的时候就回退过去。git非常强大,基本上你想到的他都可以做到,提交到仓库的数据基本不会丢失,像时间机
器一样控制着代码。

多人协作
--------

git非常强大,上面只是一个功能。考虑Tom的秘书处有两个人,他们在同时写。其中Tom写前6章,他的同伴写第7~
12章。

这时候可以考虑用这种工作的方式:设立一个公共的仓库。Tom维护自己的版本,他的同伴维护自己的版本。然后大
家定期把代码合并到公共仓库上面,然后定期把新的版本取回来合并再提交到公共仓库。

如果他们用纯文本,得益于一些文本分析的方法,几乎不需要校对就可以做到。

```
git commit -m 'finish ch5' // 假设此时Tom写完了第5章
git push // Tom将代码推送到远程仓库
```

```
git commit -m 'finish ch11' // 假设此时Tom的同伴完成了第11章
git pull // pull会将最新版本拉下来,合并,然后推送到远程仓库
```

实际上工作中,为了不混淆,会新开一个分支来开发新的特性,然后对分支进行合并。

代码自动发布
-----------

另一个很强大的功能是可以实现代码的自动发布。事实上,很多云就有使用这个。具体来说,利用git的hooks,当
服务器收到一个push,服务器可以自动运行一些脚本。也可以在客户端使用hooks,当客户端准备push的时候,客户
端先运行一些脚本。

例如,我们希望在每次服务器收到push以后,杀死全部的 `p` 进程,然后重开 `p` 进程。我们可以修改 `hooks/
post-receive` :

```
echo "Killing all p process..."
killall -9 p
echo "Restart p process..."
p
```

更多更多更多……
---------------

这份教程就到这里了,更多的自己马上动手去试试吧!

在openSUSE的安装方法:

```
sudo zypper in git
```

默认应该就装了。

一般linux命令查看帮助都是 `--help` 选项:

```
git --help
```

此外,对一个子命令也是有help看的:

```
git init --help
```

这里有一个交互教程,在浏览器上面跑的模拟git的运行的,有兴趣的试试:

<http://try.github.io/>

github的help文档写得很不错,推荐一下:

<https://help.github.com/>

书籍有个远近闻名的《Pro Git》,而且有中文版的,虽然我认为这本书太厚了。。。但似乎就这么一本书……

<http://git-scm.com/book/zh>

国内有个gitcafe,也是做git托管的,他们也有整理一份help:

<https://gitcafe.com/GitCafe/Help>

记得,上面只是一个演示,多试试push,多尝试。有一天你会喜欢用这个有效的工具的。

很有用!!! 查看全部

最流行的版本控制软件:git
========================

git已经是当前最流行的版本控制软件之一了。全世界的程序员都在使用它。它出自linus大神之手,现在被用于内
核的版本控制。在最流行的代码托管软件github,你几乎可以找到所有开源项目的代码。

版块控制软件:我需要吗?
-----------------------

的确对于许多人——尤其是非程序员,他们可能不会想到已经出现了专门的版本控制的软件。但其实多人对版本控
制其实都有类似的需求,举个例子,Tom是社团的秘书处成员,他们经常需要做的事情就是写活动文档,然后不停地
改改到大家都觉得可以了。

不幸运的话,Tom可能有个文件夹叫“openSUSE活动策划",里面有这样的一堆文件”openSUSE活动策划", "活动策
划1", "活动策划2", "活动策划3", "活动策划4" ... "活动策划20" (可怜的Tom,一份文档改了不少于20次)

这种作法很有效,因为我们可能发现第5个版本的策划有问题,我们准备在第3个版本上面重新来过。但是也看到,
这个作法有些很丑陋的地方:一份文件,我们留了20个备份,而且还要注意文件名。

如果可以这样就好了:文件夹上只有一个“openSUSE活动策划",但当我需要第5个版本的时候,我来一个”给我还
原到第5个版本吧!“,然后这时候我们打开这个文件,它就是第5个版本的了。类似的,我们可以取出任意的版本


这就是版本控制。这种事情在程序里面发生的太多了,于是出现了各种版本控制软件。事实上,有些项目已经发展
到第1000+甚至更高的版本数了……

单线的工作流
------------

我们可以把我们的一个项目想象为一个仓库,然后我们可以把我们的东西塞进仓库里面,也可以把想要的东西拿出
来。而git则是仓库的管理员。下面是一个例子,希望有一个直观的印象,不求完全的理解和掌握。

```bash
mkdir myproject // 假设myproject是工作目录
cd myproject
git init // git <- (init) ,告诉仓库管理员,在当前目录初始化
echo 'Eat the banana' > file // 编辑了一个文件
git add file // 加入仓库
git commit -m 'add first file' // 提交更改
echo 'Eat the apply' > file // 修改了这个文件
git add file // 加入仓库
git commit -m 'update first file' // 再提交更改
```

这时候我们就有两个commit了,我们来看看工作日志:

```bash
git log

# 以下是输出
# commit ac1371173b4e630ddaebda3f9f5d948b36146c07
# Author: Norman Mo <LTaoist@@@>
# Date: Thu Jun 27 21:59:10 2013 +0800
#
# update first file
#
# commit 3c43cc913454f92bb4b80c56ba45e4ffaf556fc0
# Author: Norman Mo <LTaoist6@@@@>
# Date: Thu Jun 27 21:58:48 2013 +0800
#
# add first file
```

看到了,我们提交了两次。我们来看看现在file里面是什么:

```bash
cat file # 显然输出是 'Eat the apply'
# 现在,我们来拿回第一个版本的file文件
git checkout 3c43cc913454f92bb4b80c56ba45e4ffaf556fc0 -- file
cat file # 这时候就是eat banana了
```

这种工作的方式是单人使用最常见的方式,写一点代码,提交一下到仓库里面。写一点,提交到仓库里面。然后出
问题的时候就回退过去。git非常强大,基本上你想到的他都可以做到,提交到仓库的数据基本不会丢失,像时间机
器一样控制着代码。

多人协作
--------

git非常强大,上面只是一个功能。考虑Tom的秘书处有两个人,他们在同时写。其中Tom写前6章,他的同伴写第7~
12章。

这时候可以考虑用这种工作的方式:设立一个公共的仓库。Tom维护自己的版本,他的同伴维护自己的版本。然后大
家定期把代码合并到公共仓库上面,然后定期把新的版本取回来合并再提交到公共仓库。

如果他们用纯文本,得益于一些文本分析的方法,几乎不需要校对就可以做到。

```
git commit -m 'finish ch5' // 假设此时Tom写完了第5章
git push // Tom将代码推送到远程仓库
```

```
git commit -m 'finish ch11' // 假设此时Tom的同伴完成了第11章
git pull // pull会将最新版本拉下来,合并,然后推送到远程仓库
```

实际上工作中,为了不混淆,会新开一个分支来开发新的特性,然后对分支进行合并。

代码自动发布
-----------

另一个很强大的功能是可以实现代码的自动发布。事实上,很多云就有使用这个。具体来说,利用git的hooks,当
服务器收到一个push,服务器可以自动运行一些脚本。也可以在客户端使用hooks,当客户端准备push的时候,客户
端先运行一些脚本。

例如,我们希望在每次服务器收到push以后,杀死全部的 `p` 进程,然后重开 `p` 进程。我们可以修改 `hooks/
post-receive` :

```
echo "Killing all p process..."
killall -9 p
echo "Restart p process..."
p
```

更多更多更多……
---------------

这份教程就到这里了,更多的自己马上动手去试试吧!

在openSUSE的安装方法:

```
sudo zypper in git
```

默认应该就装了。

一般linux命令查看帮助都是 `--help` 选项:

```
git --help
```

此外,对一个子命令也是有help看的:

```
git init --help
```

这里有一个交互教程,在浏览器上面跑的模拟git的运行的,有兴趣的试试:

<http://try.github.io/>

github的help文档写得很不错,推荐一下:

<https://help.github.com/>

书籍有个远近闻名的《Pro Git》,而且有中文版的,虽然我认为这本书太厚了。。。但似乎就这么一本书……

<http://git-scm.com/book/zh>

国内有个gitcafe,也是做git托管的,他们也有整理一份help:

<https://gitcafe.com/GitCafe/Help>

记得,上面只是一个演示,多试试push,多尝试。有一天你会喜欢用这个有效的工具的。

很有用!!!

python 爬虫使用urlretrieve下载时一直报错

李魔佛 回复了问题 • 2 人关注 • 1 个回复 • 376 次浏览 • 2019-04-11 09:53 • 来自相关话题