當前位置:首頁 » 編程語言 » pythonmysql多線程

pythonmysql多線程

發布時間: 2022-12-25 23:04:05

㈠ 為什麼有人說 python 的多線程是雞肋

因為 Python 中臭名昭著的 GIL。

那麼 GIL 是什麼?為什麼會有 GIL?多線程真的是雞肋嗎? GIL 可以去掉嗎?帶著這些問題,我們一起往下看,同時需要你有一點點耐心。

多線程是不是雞肋,我們先做個實驗,實驗非常簡單,就是將數字 「1億」 遞減,減到 0 程序就終止,這個任務如果我們使用單線程來執行,完成時間會是多少?使用多線程又會是多少?show me the code

那麼把 GIL 去掉可行嗎?

還真有人這么干多,但是結果令人失望,在1999年Greg Stein 和Mark Hammond 兩位哥們就創建了一個去掉 GIL 的 Python 分支,在所有可變數據結構上把 GIL 替換為更為細粒度的鎖。然而,做過了基準測試之後,去掉GIL的 Python 在單線程條件下執行效率將近慢了2倍。

Python之父表示:基於以上的考慮,去掉GIL沒有太大的價值而不必花太多精力。

㈡ python sqlalchemy 多線程怎麼寫

首先說下,由於最新的 0.8 版還是開發版本,因此我使用的是 0.79 版,API 也許會有些不同。
因為我是搭配 MySQL InnoDB 使用,所以使用其他資料庫的也不能完全照搬本文。
接著就從安裝開始介紹吧,以 Debian/Ubuntu 為例(請確保有管理員許可權):
1.MySQL

復制代碼代碼如下:
apt-get install mysql-server
apt-get install mysql-client
apt-get install libmysqlclient15-dev

2.python-mysqldb

復制代碼代碼如下:
apt-get install python-mysqldb

3.easy_install

python ez_setup.py
4.MySQL-Python

復制代碼代碼如下:
easy_install MySQL-Python

5.SQLAlchemy

復制代碼代碼如下:
easy_install SQLAlchemy
如果是用其他操作系統,遇到問題就 Google 一下吧。我是在 Mac OS X 上開發的,途中也遇到些問題,不過當時沒記下來……
值得一提的是我用了 MySQL-Python 來連 MySQL,因為不支持非同步調用,所以和 Tornado 不是很搭。不過性能其實很好,因此以後再去研究下其他方案吧……
裝好後就可以開始使用了:

復制代碼代碼如下:
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker

DB_CONNECT_STRING = 'mysql+mysqldb://root:123@localhost/ooxx?charset=utf8'
engine = create_engine(DB_CONNECT_STRING, echo=True)
DB_Session = sessionmaker(bind=engine)
session = DB_Session()

這里的 DB_CONNECT_STRING 就是連接資料庫的路徑。「mysql+mysqldb」指定了使用 MySQL-Python 來連接,「root」和「123」分別是用戶名和密碼,「localhost」是資料庫的域名,「ooxx」是使用的資料庫名(可省略),「charset」指定了連接時使用的字元集(可省略)。
create_engine() 會返回一個資料庫引擎,echo 參數為 True 時,會顯示每條執行的 SQL 語句,生產環境下可關閉。
sessionmaker() 會生成一個資料庫會話類。這個類的實例可以當成一個資料庫連接,它同時還記錄了一些查詢的數據,並決定什麼時候執行 SQL 語句。由於 SQLAlchemy 自己維護了一個資料庫連接池(默認 5 個連接),因此初始化一個會話的開銷並不大。對 Tornado 而言,可以在 BaseHandler 的 initialize() 里初始化:

復制代碼代碼如下:

class BaseHandler(tornado.web.RequestHandler):
def initialize(self):
self.session = models.DB_Session()
def on_finish(self):
self.session.close()

對其他 Web 伺服器來說,可以使用 sqlalchemy.orm.scoped_session,它能保證每個線程獲得的 session 對象都是唯一的。不過 Tornado 本身就是單線程的,如果使用了非同步方式,就可能會出現問題,因此我並沒使用它。
拿到 session 後,就可以執行 SQL 了:

復制代碼代碼如下:
session.execute('create database abc')
print session.execute('show databases').fetchall()
session.execute('use abc')
# 建 user 表的過程略
print session.execute('select * from user where id = 1').first()
print session.execute('select * from user where id = :id', {'id': 1}).first()

不過這和直接使用 MySQL-Python 沒啥區別,所以就不介紹了;我還是喜歡 ORM 的方式,這也是我採用 SQLAlchemy 的唯一原因。
於是來定義一個表:

復制代碼代碼如下:
from sqlalchemy import Column
from sqlalchemy.types import CHAR, Integer, String
from sqlalchemy.ext.declarative import declarative_base

BaseModel = declarative_base()
def init_db():
BaseModel.metadata.create_all(engine)
def drop_db():
BaseModel.metadata.drop_all(engine)

class User(BaseModel):
__tablename__ = 'user'
id = Column(Integer, primary_key=True)
name = Column(CHAR(30)) # or Column(String(30))
init_db()
declarative_base() 創建了一個 BaseModel 類,這個類的子類可以自動與一個表關聯。
以 User 類為例,它的 __tablename__ 屬性就是資料庫中該表的名稱,它有 id 和 name 這兩個欄位,分別為整型和 30 個定長字元。Column 還有一些其他的參數,我就不解釋了。
最後,BaseModel.metadata.create_all(engine) 會找到 BaseModel 的所有子類,並在資料庫中建立這些表;drop_all() 則是刪除這些表。
接著就開始使用這個表吧:

復制代碼代碼如下:
from sqlalchemy import func, or_, not_

user = User(name='a')
session.add(user)
user = User(name='b')
session.add(user)
user = User(name='a')
session.add(user)
user = User()
session.add(user)
session.commit()
query = session.query(User)
print query # 顯示SQL 語句
print query.statement # 同上
for user in query: # 遍歷時查詢
print user.name
print query.all() # 返回的是一個類似列表的對象
print query.first().name # 記錄不存在時,first() 會返回 None
# print query.one().name # 不存在,或有多行記錄時會拋出異常
print query.filter(User.id == 2).first().name
print query.get(2).name # 以主鍵獲取,等效於上句
print query.filter('id = 2').first().name # 支持字元串
query2 = session.query(User.name)
print query2.all() # 每行是個元組
print query2.limit(1).all() # 最多返回 1 條記錄
print query2.offset(1).all() # 從第 2 條記錄開始返回
print query2.order_by(User.name).all()
print query2.order_by('name').all()
print query2.order_by(User.name.desc()).all()
print query2.order_by('name desc').all()
print session.query(User.id).order_by(User.name.desc(), User.id).all()
print query2.filter(User.id == 1).scalar() # 如果有記錄,返回第一條記錄的第一個元素
print session.query('id').select_from(User).filter('id = 1').scalar()
print query2.filter(User.id > 1, User.name != 'a').scalar() # and
query3 = query2.filter(User.id > 1) # 多次拼接的 filter 也是 and
query3 = query3.filter(User.name != 'a')
print query3.scalar()
print query2.filter(or_(User.id == 1, User.id == 2)).all() # or
print query2.filter(User.id.in_((1, 2))).all() # in
query4 = session.query(User.id)
print query4.filter(User.name == None).scalar()
print query4.filter('name is null').scalar()
print query4.filter(not_(User.name == None)).all() # not
print query4.filter(User.name != None).all()
print query4.count()
print session.query(func.count('*')).select_from(User).scalar()
print session.query(func.count('1')).select_from(User).scalar()
print session.query(func.count(User.id)).scalar()
print session.query(func.count('*')).filter(User.id > 0).scalar() # filter() 中包含 User,因此不需要指定表
print session.query(func.count('*')).filter(User.name == 'a').limit(1).scalar() == 1 # 可以用 limit() 限制 count() 的返回數
print session.query(func.sum(User.id)).scalar()
print session.query(func.now()).scalar() # func 後可以跟任意函數名,只要該資料庫支持
print session.query(func.current_timestamp()).scalar()
print session.query(func.md5(User.name)).filter(User.id == 1).scalar()
query.filter(User.id == 1).update({User.name: 'c'})
user = query.get(1)
print user.name
user.name = 'd'
session.flush() # 寫資料庫,但並不提交
print query.get(1).name
session.delete(user)
session.flush()
print query.get(1)
session.rollback()
print query.get(1).name
query.filter(User.id == 1).delete()
session.commit()
print query.get(1)

增刪改查都涉及到了,自己看看輸出的 SQL 語句就知道了,於是基礎知識就介紹到此了。

下面開始介紹一些進階的知識。
如何批量插入大批數據?

可以使用非 ORM 的方式:

復制代碼代碼如下:
session.execute(
User.__table__.insert(),
[{'name': `randint(1, 100)`,'age': randint(1, 100)} for i in xrange(10000)]
)
session.commit()

上面我批量插入了 10000 條記錄,半秒內就執行完了;而 ORM 方式會花掉很長時間。
如何讓執行的 SQL 語句增加前綴?

使用 query 對象的 prefix_with() 方法:

復制代碼代碼如下:
session.query(User.name).prefix_with('HIGH_PRIORITY').all()
session.execute(User.__table__.insert().prefix_with('IGNORE'), {'id': 1, 'name': '1'})
如何替換一個已有主鍵的記錄?

使用 session.merge() 方法替代 session.add(),其實就是 SELECT + UPDATE:

復制代碼代碼如下:
user = User(id=1, name='ooxx')
session.merge(user)
session.commit()

或者使用 MySQL 的 INSERT … ON DUPLICATE KEY UPDATE,需要用到 @compiles 裝飾器,有點難懂,自己搜索看吧:《SQLAlchemy ON DUPLICATE KEY UPDATE》 和 sqlalchemy_mysql_ext。
如何使用無符號整數?

可以使用 MySQL 的方言:

復制代碼代碼如下:
from sqlalchemy.dialects.mysql import INTEGER
id = Column(INTEGER(unsigned=True), primary_key=True)
模型的屬性名需要和表的欄位名不一樣怎麼辦?

開發時遇到過一個奇怪的需求,有個其他系統的表裡包含了一個「from」欄位,這在 Python 里是關鍵字,於是只能這樣處理了:

復制代碼代碼如下:
from_ = Column('from', CHAR(10))
如何獲取欄位的長度?

Column 會生成一個很復雜的對象,想獲取長度比較麻煩,這里以 User.name 為例:

復制代碼代碼如下:
User.name.property.columns[0].type.length
如何指定使用 InnoDB,以及使用 UTF-8 編碼?

最簡單的方式就是修改資料庫的默認配置。如果非要在代碼里指定的話,可以這樣:

復制代碼代碼如下:
class User(BaseModel):
__table_args__ = {
'mysql_engine': 'InnoDB',
'mysql_charset': 'utf8'
}

MySQL 5.5 開始支持存儲 4 位元組的 UTF-8 編碼的字元了,iOS 里自帶的 emoji(如 �� 字元)就屬於這種。
如果是對表來設置的話,可以把上面代碼中的 utf8 改成 utf8mb4,DB_CONNECT_STRING 里的 charset 也這樣更改。
如果對庫或欄位來設置,則還是自己寫 SQL 語句比較方便,具體細節可參考《How to support full Unicode in MySQL databases》。
不建議全用 utf8mb4 代替 utf8,因為前者更慢,索引會佔用更多空間。
如何設置外鍵約束?

復制代碼代碼如下:
from random import randint
from sqlalchemy import ForeignKey

class User(BaseModel):
__tablename__ = 'user'
id = Column(Integer, primary_key=True)
age = Column(Integer)

class Friendship(BaseModel):
__tablename__ = 'friendship'
id = Column(Integer, primary_key=True)
user_id1 = Column(Integer, ForeignKey('user.id'))
user_id2 = Column(Integer, ForeignKey('user.id'))

for i in xrange(100):
session.add(User(age=randint(1, 100)))
session.flush() # 或 session.commit(),執行完後,user 對象的 id 屬性才可以訪問(因為 id 是自增的)
for i in xrange(100):
session.add(Friendship(user_id1=randint(1, 100), user_id2=randint(1, 100)))
session.commit()
session.query(User).filter(User.age < 50).delete()
執行這段代碼時,你應該會遇到一個錯誤:

復制代碼代碼如下:
sqlalchemy.exc.IntegrityError: (IntegrityError) (1451, 'Cannot delete or update a parent row: a foreign key constraint fails (`ooxx`.`friendship`, CONSTRAINT `friendship_ibfk_1` FOREIGN KEY (`user_id1`) REFERENCES `user` (`id`))') 'DELETE FROM user WHERE user.age < %s' (50,)

原因是刪除 user 表的數據,可能會導致 friendship 的外鍵不指向一個真實存在的記錄。在默認情況下,MySQL 會拒絕這種操作,也就是 RESTRICT。InnoDB 還允許指定 ON DELETE 為 CASCADE 和 SET NULL,前者會刪除 friendship 中無效的記錄,後者會將這些記錄的外鍵設為 NULL。
除了刪除,還有可能更改主鍵,這也會導致 friendship 的外鍵失效。於是相應的就有 ON UPDATE 了。其中 CASCADE 變成了更新相應的外鍵,而不是刪除。
而在 SQLAlchemy 中是這樣處理的:

復制代碼代碼如下:
class Friendship(BaseModel):
__tablename__ = 'friendship'
id = Column(Integer, primary_key=True)
user_id1 = Column(Integer, ForeignKey('user.id', ondelete='CASCADE', onupdate='CASCADE'))
user_id2 = Column(Integer, ForeignKey('user.id', ondelete='CASCADE', onupdate='CASCADE'))
如何連接表?

復制代碼代碼如下:
from sqlalchemy import distinct
from sqlalchemy.orm import aliased

Friend = aliased(User, name='Friend')
print session.query(User.id).join(Friendship, User.id == Friendship.user_id1).all() # 所有有朋友的用戶
print session.query(distinct(User.id)).join(Friendship, User.id == Friendship.user_id1).all() # 所有有朋友的用戶(去掉重復的)
print session.query(User.id).join(Friendship, User.id == Friendship.user_id1).distinct().all() # 同上
print session.query(Friendship.user_id2).join(User, User.id == Friendship.user_id1).order_by(Friendship.user_id2).distinct().all() # 所有被別人當成朋友的用戶
print session.query(Friendship.user_id2).select_from(User).join(Friendship, User.id == Friendship.user_id1).order_by(Friendship.user_id2).distinct().all() # 同上,join 的方向相反,但因為不是 STRAIGHT_JOIN,所以 MySQL 可以自己選擇順序
print session.query(User.id, Friendship.user_id2).join(Friendship, User.id == Friendship.user_id1).all() # 用戶及其朋友
print session.query(User.id, Friendship.user_id2).join(Friendship, User.id == Friendship.user_id1).filter(User.id < 10).all() # id 小於 10 的用戶及其朋友
print session.query(User.id, Friend.id).join(Friendship, User.id == Friendship.user_id1).join(Friend, Friend.id == Friendship.user_id2).all() # 兩次 join,由於使用到相同的表,因此需要別名
print session.query(User.id, Friendship.user_id2).outerjoin(Friendship, User.id

㈢ Python多線程是什麼意思

簡單地說就是作為可能是僅有的支持多線程的解釋型語言(perl的多線程是殘疾,PHP沒有多線程),Python的多線程是有compromise的,在任意時間只有一個Python解釋器在解釋Python bytecode。
UPDATE:如評論指出,Ruby也是有thread支持的,而且至少Ruby MRI是有GIL的。
如果你的代碼是CPU密集型,多個線程的代碼很有可能是線性執行的。所以這種情況下多線程是雞肋,效率可能還不如單線程因為有context switch
但是:如果你的代碼是IO密集型,多線程可以明顯提高效率。例如製作爬蟲(我就不明白為什麼Python總和爬蟲聯系在一起…不過也只想起來這個例子…),絕大多數時間爬蟲是在等待socket返回數據。這個時候C代碼里是有release GIL的,最終結果是某個線程等待IO的時候其他線程可以繼續執行。
反過來講:你就不應該用Python寫CPU密集型的代碼…效率擺在那裡…
如果確實需要在CPU密集型的代碼里用concurrent,就去用multiprocessing庫。這個庫是基於multi process實現了類multi thread的API介面,並且用pickle部分地實現了變數共享。
再加一條,如果你不知道你的代碼到底算CPU密集型還是IO密集型,教你個方法:
multiprocessing這個mole有一個mmy的sub mole,它是基於multithread實現了multiprocessing的API。
假設你使用的是multiprocessing的Pool,是使用多進程實現了concurrency
from multiprocessing import Pool
如果把這個代碼改成下面這樣,就變成多線程實現concurrency
from multiprocessing.mmy import Pool
兩種方式都跑一下,哪個速度快用哪個就行了。
UPDATE:
剛剛才發現concurrent.futures這個東西,包含ThreadPoolExecutor和ProcessPoolExecutor,可能比multiprocessing更簡單

㈣ python多線程能提高效率嗎

很多爬蟲工作者都遇到過抓取速度非常慢,現在的大多數網站都具備了反爬蟲技術,對IP的訪問頻率限制很嚴格。如果想提升爬蟲的速度,大家可以嘗試以下方法。

一、盡量減少訪問次數。
單次爬蟲任務的大多耗時在網路請求等待響應,所以能減少網路請求就盡量減少請求,這樣既能減少目標網站的壓力,也能減少代理伺服器的壓力,提高工作效率。

二、精簡流程,減少重復。
大部分網站並不是嚴格意義上的樹狀結構,而是多重交叉的網狀結構,所以從多個入口深入的網頁會有很多重復,一般根據URL或者ID進行唯一性判別,爬過的就不需要再爬。一些數據如果可以在一個頁面內獲取到,也可以在多個頁面下獲取到,那就選擇只在一個頁面內獲取。

三、多線程任務。
大量爬蟲是一個IO阻塞的任務,所以採用多線程的並發方式可以有效地提高整體速度。多線程可以更好地提高資源利用率,程序設計也更加堅定,程序響應也更快。

四、分布式任務。
上面三點都做到極致了,但是單機單位時間內能爬取到的網頁數量還不足以達到目標,在指定時間內還不能及時的完成任務,那麼就只能多機器來同時進行爬蟲任務了,這就是分布式爬蟲。

做好以上幾點,基本可以將爬蟲的效率提升大半,另外爬蟲代理ip也是不可缺少的尤其是對於量大的任務,IPIDEA提供全球ip的同時更注重保護數據的安全,也可以減少反爬蟲策略的觸發,一舉多得。

㈤ python 多進程和多線程配合

由於python的多線程中存在PIL鎖,因此python的多線程不能利用多核,那麼,由於現在的計算機是多核的,就不能充分利用計算機的多核資源。但是python中的多進程是可以跑在不同的cpu上的。因此,嘗試了多進程+多線程的方式,來做一個任務。比如:從中科大的鏡像源中下載多個rpm包。
#!/usr/bin/pythonimport reimport commandsimport timeimport multiprocessingimport threadingdef download_image(url):
print '*****the %s rpm begin to download *******' % url
commands.getoutput('wget %s' % url)def get_rpm_url_list(url):
commands.getoutput('wget %s' % url)
rpm_info_str = open('index.html').read()

regu_mate = '(?<=<a href=")(.*?)(?=">)'
rpm_list = re.findall(regu_mate, rpm_info_str)

rpm_url_list = [url + rpm_name for rpm_name in rpm_list] print 'the count of rpm list is: ', len(rpm_url_list) return rpm_url_
def multi_thread(rpm_url_list):
threads = [] # url = 'https://mirrors.ustc.e.cn/centos/7/os/x86_64/Packages/'
# rpm_url_list = get_rpm_url_list(url)
for index in range(len(rpm_url_list)): print 'rpm_url is:', rpm_url_list[index]
one_thread = threading.Thread(target=download_image, args=(rpm_url_list[index],))
threads.append(one_thread)

thread_num = 5 # set threading pool, you have put 4 threads in it
while 1:
count = min(thread_num, len(threads)) print '**********count*********', count ###25,25,...6707%25

res = [] for index in range(count):
x = threads.pop()
res.append(x) for thread_index in res:
thread_index.start() for j in res:
j.join() if not threads:
def multi_process(rpm_url_list):
# process num at the same time is 4
process = []
rpm_url_group_0 = []
rpm_url_group_1 = []
rpm_url_group_2 = []
rpm_url_group_3 = [] for index in range(len(rpm_url_list)): if index % 4 == 0:
rpm_url_group_0.append(rpm_url_list[index]) elif index % 4 == 1:
rpm_url_group_1.append(rpm_url_list[index]) elif index % 4 == 2:
rpm_url_group_2.append(rpm_url_list[index]) elif index % 4 == 3:
rpm_url_group_3.append(rpm_url_list[index])
rpm_url_groups = [rpm_url_group_0, rpm_url_group_1, rpm_url_group_2, rpm_url_group_3] for each_rpm_group in rpm_url_groups:
each_process = multiprocessing.Process(target = multi_thread, args = (each_rpm_group,))
process.append(each_process) for one_process in process:
one_process.start() for one_process in process:
one_process.join()# for each_url in rpm_url_list:# print '*****the %s rpm begin to download *******' %each_url## commands.getoutput('wget %s' %each_url)
def main():
url = 'https://mirrors.ustc.e.cn/centos/7/os/x86_64/Packages/'
url_paas = 'http://mirrors.ustc.e.cn/centos/7.3.1611/paas/x86_64/openshift-origin/'
url_paas2 ='http://mirrors.ustc.e.cn/fedora/development/26/Server/x86_64/os/Packages/u/'

start_time = time.time()
rpm_list = get_rpm_url_list(url_paas) print multi_process(rpm_list) # print multi_thread(rpm_list)
#print multi_process()
# print multi_thread(rpm_list)
# for index in range(len(rpm_list)):
# print 'rpm_url is:', rpm_list[index]
end_time = time.time() print 'the download time is:', end_time - start_timeprint main()123456789101112131415161718

代碼的功能主要是這樣的:
main()方法中調用get_rpm_url_list(base_url)方法,獲取要下載的每個rpm包的具體的url地址。其中base_url即中科大基礎的鏡像源的地址,比如:http://mirrors.ustc.e.cn/centos/7.3.1611/paas/x86_64/openshift-origin/,這個地址下有幾十個rpm包,get_rpm_url_list方法將每個rpm包的url地址拼出來並返回。
multi_process(rpm_url_list)啟動多進程方法,在該方法中,會調用多線程方法。該方法啟動4個多進程,將上面方法得到的rpm包的url地址進行分組,分成4組,然後每一個組中的rpm包再最後由不同的線程去執行。從而達到了多進程+多線程的配合使用。
代碼還有需要改進的地方,比如多進程啟動的進程個數和rpm包的url地址分組是硬編碼,這個還需要改進,畢竟,不同的機器,適合同時啟動的進程個數是不同的。

㈥ python 怎麼實現多線程的

線程也就是輕量級的進程,多線程允許一次執行多個線程,Python是多線程語言,它有一個多線程包,GIL也就是全局解釋器鎖,以確保一次執行單個線程,一個線程保存GIL並在將其傳遞給下一個線程之前執行一些操作,也就產生了並行執行的錯覺。

㈦ python中多進程和多線程的區別

什麼是線程、進程?
進程(process)與線程(thread)是操作系統的基本概念,它們比較抽象,不容易掌握。
關於這兩者,最經典的一句話就是「進程是資源分配的最小單位,線程是CPU調度的最小單位」,線程是程序中一個單一的順序控制流程,進程內一個相對獨立的、可調度的執行單元,是系統獨立調度和分配CPU的基本單位指運行中的程序的調度單位,在單個程序中同時運行多個線程完成不同的工作,稱為多線程。
進程與線程的區別是什麼?
進程是資源分配的基本單位,所有與該進程有關的資源,都被記錄在進程式控制制塊PCB中,以表示該進程擁有這些資源或正在使用它們,另外,進程也是搶占處理機的調度單位,它擁有一個完整的虛擬地址空間,當進程發生調度時,不同的進程擁有不同的虛擬地址空間,而同一進程內的不同線程共享同一地址空間。
與進程相對應的,線程與資源分配無關,它屬於某一個進程,並與進程內的其他線程一起共享進程的資源,線程只由相關堆棧(系統棧或用戶棧)寄存器和線程式控制製表TCB組成,寄存器可被用來存儲線程內的局部變數,但不能存儲其他線程的相關變數。
通常在一個進程中可以包含若干個線程,它們可以利用進程所擁有的資源,在引入線程的操作系統中,通常都是把進程作為分配資源的基本單位,而把線程作為獨立運行和獨立調度的基本單位。
由於線程比進程更小,基本上不擁有系統資源,所以對它的調度所付出的開銷就會小得多,能更高效的提高系統內多個程序間並發執行的程度,從而顯著提高系統資源的利用率和吞吐量。
因而近年來推出的通用操作系統都引入了線程,以便進一步提高系統的並發性,並把它視為現代操作系統的一個重要指標。

㈧ 請教python如何開啟多線程

可以定義函數把這些代碼放在不同的函數里,然後threading模塊
import threading
th1 = threading.Thread(target=func1, args=(arg1, arg2, ...))
照這樣再定義別的線程,開啟用Thread類的start方法
th1.start(); th2.start(); ...

㈨ Python之MySQL操作

MySQL 是目前使用最廣泛的資料庫之一,它有著良好的性能,能夠跨平台,支持分布式,能夠承受高並發。下載地址: MySQL :: Download MySQL Community Server 安裝參考: 圖解MySQL5.7.20免安裝版配置方法-網路經驗 (.com)

Python 大致有如下 5 種方式操作 MySQL。

先使用如下建表語句創建一張簡單的資料庫表。

2.1 mysqlclient

執行 pip install mysqlclient 進行安裝,看一下具體操作。

新增

查詢

cursor 查看方法

修改

刪除

2.2 PyMySQL

執行 pip install pymysql 進行安裝,使用方式與 mysqlclient 基本類似。

2.3 peewee

執行 pip install peewee 進行安裝,看一下具體操作。

定義映射類

新增

查詢

修改

刪除

2.4 SQLAlchemy

執行 pip install sqlalchemy 進行安裝,看一下具體操作。

定義映射類

新增

查詢

修改

刪除

Python學習日記

㈩ MySQL-python連接MySQL資料庫問題,總是拋異常。

不要剛開始學多線程編程就這樣玩。connection 和 cursor 都不是線程安全的。

如果測試環境用多個線程,每個線程要在線程裡面獲取自己的 connection,然後從這個connection 獲取 cursor.

如果生產環境用多個線程,建議使用線程安全的連接池。

熱點內容
如何評價一個伺服器的性能 發布:2025-05-17 23:40:53 瀏覽:270
淘寶客適合什麼伺服器 發布:2025-05-17 23:39:26 瀏覽:612
python循環文件 發布:2025-05-17 23:39:22 瀏覽:828
androidstudio更新 發布:2025-05-17 23:38:22 瀏覽:643
java項目面試 發布:2025-05-17 23:30:53 瀏覽:780
若主存儲器按位元組編址 發布:2025-05-17 23:30:46 瀏覽:24
kotlinandroid 發布:2025-05-17 23:19:09 瀏覽:974
雲編程英語 發布:2025-05-17 23:18:34 瀏覽:623
androidstudio導入類 發布:2025-05-17 23:15:36 瀏覽:237
私人電腦伺服器如何設置 發布:2025-05-17 23:14:48 瀏覽:366