Python gelişmiş hata ayıklama becerileri (iki) IPython hata ayıklama becerileri (öğrenme yolları ve PDF dahil)

Yazılım geliştirme araçları

Önceki makale serisi, ipython'un çeşitli tekniklerini ayrıntılı olarak tanıttı. Hata ayıklama serisi (1), pdb hata ayıklamanın orijinal ekolojisini tanıttı, bkz:

Python gelişmiş hata ayıklama becerileri (1) - pdb hata ayıklamanın orijinal ekolojisi

Hata ayıklama serisinin ikinci makalesi olan bu makale, ipython tabanlı pdb hata ayıklamayı tanıtmaktadır.Mükemmel bir etkileşimli bilgi işlem ve veri keşif ortamı olmasının yanı sıra, IPython aynı zamanda etkili bir Python yazılım geliştirme aracıdır. Veri analizinde en önemli şey doğru koda sahip olmaktır. Neyse ki IPython, Python'un yerleşik pdb hata ayıklayıcısını sıkı bir şekilde entegre eder ve geliştirir. İkincisi, hızlı kod gereklidir. Bunun için IPython, kullanımı kolay kod zamanlama ve analiz araçlarına sahiptir. Bu araçları detaylı olarak tanıtacağım.

içindekiler

Bir etkileşimli hata ayıklayıcı

Hata ayıklayıcıyı kullanmanın diğer iki yolu

Üç kod zamanlaması:% time ve% timeit

Dört temel analiz:% prun ve% run -p

Beş satır satır analiz işlevi

01

Etkileşimli hata ayıklayıcı

IPython hata ayıklayıcı sekme tamamlama, sözdizimi geliştirme ve satır satır istisna izleme ile pdb'yi geliştirir. Kodda hata ayıklamak için en iyi zaman, bir hatanın henüz oluştuğu zamandır. İstisna oluştuktan sonra, hata ayıklayıcıyı başlatmak için% debug girin ve istisnanın atıldığı yığın çerçevesini girin:

In: örnekleri çalıştırın / ipython_bug.py

-------------------------------------------------- -------------------

------

AssertionError Traceback (en son çağrı

son)

/home/wesm/code/pydata-book/examples/ipython_bug.py in < modül > ()

13 throws_an_exception ()

14 --- > 15 arayan_ şeyler ()

/home/wesm/code/pydata-book/examples/ipython_bug.py in

arayan_ şeyler ()

11 def arama_ şeyler ():

12 works_fine ()

--- > 13 throws_an_exception ()

14

15 arayan_ şeyler ()

/home/wesm/code/pydata-book/examples/ipython_bug.py in

throws_an_exception ()

7 a = 5

8 b = 6

---- > 9 iddia (a + b == 10)

10

11 def arama_ şeyler ():

Onay Hatası:

In:% hata ayıklama

> /home/wesm/code/pydatabook/examples/ipython_bug.py (9) throws_an_exception ()

8 b = 6

---- > 9 iddia (a + b == 10)

10

ipdb >

Hata ayıklayıcıya girdikten sonra, her yığın çerçevesindeki tüm nesneleri ve verileri inceleyerek rastgele Python kodu çalıştırabilirsiniz (yorumlayıcı bunları etkin tutacaktır). Varsayılan, hatanın oluştuğu en düşük seviyeden başlamaktır. U (yukarı) ve d (aşağı) ile, farklı yığın izleme seviyeleri arasında geçiş yapabilirsiniz:

ipdb > sen

> /home/wesm/code/pydatabook/examples/ipython_bug.py (13) calling_things ()

12 works_fine ()

--- > 13 throws_an_exception ()

14

% Pdb komutunu çalıştırarak, IPython herhangi bir istisna oluştuğunda otomatik olarak hata ayıklayıcıyı başlatabilir.Çoğu kullanıcı bu işlevi çok yararlı bulacaktır.

Ayrıca, özellikle her aşamanın durumunu kontrol etmek için kesme noktaları ayarlamak veya işlevler ve komut dosyaları arasında geçiş yapmak istediğinizde, kod geliştirmeye yardımcı olmak için bir hata ayıklayıcı kullanmak da kolaydır. Bunu yapmanın birçok yolu var. Birincisi, betiğe geçirilen herhangi bir kodu çalıştırmadan önce hata ayıklayıcıyı çağıracak olan% run ve -d kullanmaktır. Komut dosyasını girmek için hemen s (adım) tuşuna basmalısınız:

In: run -d örnekleri / ipython_bug.py

Kesme noktası 1 /home/wesm/code/pydata-book/examples/ipython_bug.py:1

NOT: ipdb'de 'c' girin > komut dosyanızı başlatmak için komut istemi.

> < dizi > (1) < modül > ()

ipdb > s

--Aramak--

> /home/wesm/code/pydata-book/examples/ipython_bug.py(1) < modül > ()

1 --- > 1 def works_fine ():

2 a = 5

3 b = 6

O zaman nasıl çalışacağınıza karar verebilirsiniz. Örneğin, önceki istisnada, works_fine çağrılmadan hemen önce bir kesme noktası ayarlayabilir ve ardından betiği çalıştırabilir, kesme noktasıyla karşılaşıldığında c (devam) tuşuna basabiliriz:

ipdb > b 12

ipdb > c

> /home/wesm/code/pydatabook/examples/ipython_bug.py (12) arama_things ()

11 def arama_ şeyler ():

2-- > 12 works_fine ()

13 throws_an_exception ()

Şu anda, bir sonraki satıra girmek için works_fine () işlevine girebilir veya n (sonraki) tuşuna basarak works_fine () işlemini yürütebilirsiniz:

ipdb > n

> /home/wesm/code/pydatabook/examples/ipython_bug.py (13) calling_things ()

212 works_fine ()

--- > 13 throws_an_exception ()

14

Daha sonra throws_an_exception girebilir, hatanın oluştuğu satıra ulaşabilir ve değişkenleri görebiliriz. Hata ayıklayıcı komutunun değişken adından önce bir ünlem işareti eklemek olduğunu unutmayın! İçeriği görüntüleyebilir:

ipdb > s

--Aramak--

> /home/wesm/code/pydatabook/examples/ipython_bug.py (6) throws_an_exception ()

5

---- > 6 def throws_an_exception ():

7 a = 5

ipdb > n

> /home/wesm/code/pydatabook/examples/ipython_bug.py (7) throws_an_exception ()

6 def throws_an_exception ():

---- > 7 a = 5

8 b = 6

ipdb > n

> /home/wesm/code/pydatabook/examples/ipython_bug.py (8) throws_an_exception ()

7 a = 5

---- > 8 b = 6

9 assert (a + b == 10) ipdb > n

> /home/wesm/code/pydatabook/examples/ipython_bug.py (9) throws_an_exception ()

8 b = 6

---- > 9 iddia (a + b == 10)

10

ipdb > ! a

5

ipdb > ! b

6

Etkileşimli hata ayıklayıcıyı kullanma yeterliliğini geliştirmek, pratik ve deneyim gerektirir. Tablo B-2, tüm hata ayıklayıcı komutlarını listeler. IDE'ye alışkınsanız, terminalin hata ayıklayıcısının ilk başta rahatsız olacağını düşünebilirsiniz, ancak kullanımı daha kolay hale gelecektir. Bazı Python IDE'lerinin iyi GUI hata ayıklayıcıları vardır, sadece kullanımı kolay olanı seçin.

02

Hata ayıklayıcıyı kullanmanın diğer yolları

Hata ayıklayıcıyı kullanabilen başka görevler de vardır. Birincisi, basit bir kesme noktası olan özel set_trace işlevini (pdb.set_trace olarak adlandırılır) kullanmaktır. Kullanmak isteyebileceğiniz iki yöntem daha var

(Benim gibi, IPython yapılandırmasına ekleyin):

IPython.core.debugger'dan içe aktarma Pdb

def set_trace ():

Pdb (color_scheme = 'Linux'). Set_trace (sys._getframe (). F_back)

def hata ayıklama (f, * args, ** kwargs):

pdb = Pdb (color_scheme = 'Linux')

return pdb.runcall (f, * args, ** kwargs)

İlk set_trace işlevi çok basittir. Daha yakın bir inceleme için geçici olarak durmak istiyorsanız (örneğin, bir istisna oluşmadan önce), set_trace'i kodun herhangi bir yerinde kullanabilirsiniz:

In: örnekleri çalıştırın / ipython_bug.py

> /home/wesm/code/pydatabook/examples/ipython_bug.py (16) calling_things ()

15 set_trace ()

--- > 16 throws_an_exception ()

17

Kodun normal şekilde ilerlemeye devam etmesine izin vermek için c (devam) tuşuna basın.

Az önce baktığımız hata ayıklama işlevi, herhangi bir işlevi çağırırken hata ayıklayıcıyı rahatça kullanmanıza izin verir. Aşağıdaki işlevi yazdığımızı ve mantığını adım adım analiz etmek istediğimizi varsayalım:

def f (x, y, z = 1):

tmp = x + y

dönüş tmp / z

Normalde f kullanın, f (1, 2, z = 3) gibi olacaktır. F'yi girmek için, hata ayıklanacak ilk parametre olarak f'yi iletin ve ardından konum ve anahtar kelime parametrelerini f'ye iletin:

In: hata ayıklama (f, 1, 2, z = 3)

> < ipython-girişi > (2) f ()

1 def f (x, y, z):

---- > 2 tmp = x + y3 dönüş tmp / z

ipdb >

Bu iki basit yöntem bana çok zaman kazandırdı.

Son olarak, hata ayıklayıcı% run ile kullanılabilir. Komut dosyası,% run -d komutunu çalıştırarak doğrudan hata ayıklayıcıya girebilir, kesme noktalarını istediğiniz gibi ayarlayabilir ve komut dosyasını başlatabilir:

İçinde:% run -d örnekleri / ipython_bug.py

Kesme noktası 1 /home/wesm/code/pydata-book/examples/ipython_bug.py:1

NOT: ipdb'de 'c' girin > komut dosyanızı başlatmak için komut istemi.

> < dizi > (1) < modül > ()

ipdb >

-B ve satır numarası ekleyin, bir kesme noktası önceden ayarlayabilirsiniz:

İçinde:% run -d -b2 örnekler / ipython_bug.py

Kesme noktası 1 /home/wesm/code/pydata-book/examples/ipython_bug.py:2

NOT: ipdb'de 'c' girin > komut dosyanızı başlatmak için komut istemi.

> < dizi > (1) < modül > ()

ipdb > c

> /home/wesm/code/pydata-book/examples/ipython_bug.py (2) works_fine ()

1 def works_fine ():

1 --- > 2 a = 5

3 b = 6

ipdb >

03

Kod zamanlaması:% time ve% timeit

Büyük ve uzun süreli veri analizi uygulamaları için, farklı bileşenlerin veya bağımsız işlev çağrı deyimlerinin yürütme süresini ölçmek isteyebilirsiniz. Hangi işlevin en uzun sürdüğünü bilmek isteyebilirsiniz. Neyse ki, IPython, kodu geliştirirken ve test ederken bu bilgileri kolayca elde etmenizi sağlar.

Manüel olarak zaman modülünü ve zaman.clock ve time.time işlevlerini kullanın, monoton ve tekrarlayan kod, çünkü bazı sıkıcı şablonlu kodların yazılması gerekir:

ithalat zamanı

start = time.time ()

aralıktaki i için (yinelemeler):

# burada çalıştırılacak bazı kodlar

elapsed_per = (time.time () - başlangıç) / yinelemeler

Bu çok yaygın bir işlem olduğu için, IPython'un bu işlemi otomatikleştirebilen iki sihirli işlevi vardır:% time ve% timeit.

% time ifadeyi bir kez çalıştıracak ve toplam yürütme süresini bildirecektir. Büyük bir dizge listemiz olduğunu ve belirli başlangıç dizelerini seçebilen farklı yöntemleri karşılaştırmak istediğimizi varsayalım. 600.000 dizeden oluşan bir liste ve foo ile başlayan dizeleri seçmek için iki yöntem:

# çok geniş bir dizi listesi

dizeler = * 100000

method1 =

method2 =

Görünüşe göre performansları aynı seviyede olmalı, peki ya gerçek? Aşağıdaki ölçümü yapmak için% time değerini kullanın:

İçinde:% zaman yöntemi1 =

CPU süreleri: kullanıcı 0,19 s, sys: 0,00 s, toplam: 0,19 s

Duvar süresi: 0,19 sn

Giriş:% zaman yöntemi2 = CPU süreleri: kullanıcı 0,09 sn, sys: 0,00 sn, toplam: 0,09 sn

Duvar süresi: 0,09 s

Duvar saati (duvar saati süresinin kısaltması) ana sorundur. İlk yöntem, ikinci yöntemin iki katından fazladır, ancak bu ölçüm yöntemi doğru değildir. Birden çok kez ölçmek için% time kullanırsanız, sonucun değiştiğini göreceksiniz. Daha doğru olmak için,% timeit sihirli işlevini kullanabilirsiniz. Herhangi bir ifade verildiğinde, daha doğru bir zaman elde etmek için bu ifadeyi birden çok kez çalıştırabilir:

İçinde:% timeit

10 döngü, döngü başına en iyi 3: 159 ms

İçinde:% timeit

10 döngü, döngü başına en iyi 3: 59,3 ms

Bu örnek, Python standart kitaplığı, NumPy, pandalar ve diğer kitaplıkların performansını anlamanın değerini göstermektedir. Büyük ölçekli veri analizinde bu milisaniyeler birikecek!

% timeit, mikrosaniye veya nanosaniye cinsinden bile kısa yürütme sürelerine sahip ifadeleri ve işlevleri analiz etmek için özellikle uygundur. Bu zamanlar önemsiz görünebilir, ancak 1 milyon kez yürütülen 20 mikrosaniye işlevi, 5 mikrosaniye işlevinden 15 saniye daha uzundur. Önceki örnekte, performans özelliklerini anlamak için iki dizi işlemini doğrudan karşılaştırabiliriz:

İçinde: x = 'foobar'

İçinde: y = 'foo'

İçinde:% timeit x.startswith (y)

1000000 döngü, döngü başına en iyi 3: 267 ns

İçinde:% timeit x == y

10000000 döngü, döngü başına en iyi 3: 147 ns

04

Temel analiz:% prun ve% run -p

Analiz kodu, "zamanın nerede harcandığına" odaklanması dışında kod zamanlamasıyla yakından ilgilidir. Python için ana analiz aracı, IPython ile sınırlı olmayan cProfile modülüdür. cProfile, bir program veya isteğe bağlı kod bloğu yürütecek ve her işlevin yürütme süresini izleyecektir.

CProfile'ı kullanmanın genel yolu, tüm programı komut satırında çalıştırmak ve her işlevin toplam süresini çıkarmaktır. Bir döngüde doğrusal cebir işlemlerini gerçekleştiren basit bir betiğimiz olduğunu varsayalım (100 × 100 matris serisinin maksimum mutlak özdeğerini hesaplar):

numpy'yi np olarak içe aktar

numpy.linalg'den ithal eigvals

def run_experiment (niter = 100):

K = 100

sonuçlar =

xrange (niter) içinde _ için:

mat = np.random.randn (K, K)

max_eigenvalue = np.abs (eigval (mat)). max ()

results.append (max_eigenvalue)

sonuçları döndür

some_results = run_experiment ()

print'En büyük gördüğümüz:% s '% np.max (some_results)

Bu betiği aşağıdaki komut satırını kullanarak cProfile ile çalıştırabilirsiniz:

python -m cProfile cprof_example.py

Çalıştırdıktan sonra, çıktının işlev adına göre sıralandığını göreceksiniz. Kimin daha fazla zaman harcadığını görmek biraz zor, sıralamayı belirtmek için -s kullanmak en iyisidir:

$ python -m cProfile -s kümülatif cprof_example.py

Gördüğümüz en büyüğü: 11.923204422

15116 işlev çağrısı (14927 ilkel çağrı) 0,720 saniyede

Sıralama ölçütü: kümülatif zaman çağrıları tottime percall cumtime percall dosya adı: lineno (işlev)

10,0010,0010,7210,721

cprof_example.py:1 ( < modül > )

1000.0030.0000.5860.006 linalg.py:702(eigvals)

2000,5720,0030,5720,003

{numpy.linalg.lapack_lite.dgeev}

10,0020,0020,0750,075 __init __. Py: 106 ( < modül > )

1000.0590.0010.0590.001 {method'randn ')

10.0000.0000.0440.044 add_newdocs.py:9 ( < modül > )

20,0010,0010,0370,019 __init __. Py: 1 ( < modül > )

20,0030,0020,0300,015 __init__.py: 2 ( < modül > )

10.0000.0000.0300.030 type_check.py: 3 ( < modül > )

10,0010,0010,0210,021 __init __. Py: 15 ( < modül > )

10,0130,0130,0130,013 numeric.py:1 ( < modül > )

10.0000.0000.0090.009 __init __. Py: 6 ( < modül > )

10,0010,0010,0080,008 __init __. Py: 45 ( < modül > )

2620,0050,0000,0070,000

function_base.py:3178(add_newdoc)

1000.0030.0000.0050.000

linalg.py:162(_assertFinite)

Yalnızca ilk 15 satır görüntülenir. Cumtime sütununu tarayarak, her işlevin ne kadar zaman aldığını kolayca görebilirsiniz. Bir işlev diğer işlevleri çağırırsa, zamanlama durmaz. cProfile, her bir işlevin başlangıç ve bitiş zamanını kaydedecek ve bunları zamanlama için kullanacaktır.

Komut satırında kullanılmasının yanı sıra cProfile, yeni bir işlem çalıştırmaya gerek kalmadan rastgele kod bloklarını analiz etmek için programlarda da kullanılabilir. Ipython'un% prun ve% run -p bu işlevi gerçekleştirmek için uygun arabirimlere sahiptir. % prun, cProfile'a benzer komut satırı seçeneklerini kullanır, ancak tüm py dosyasını kullanmadan rastgele Python ifadelerini analiz edebilir:

İçinde:% prun -l 7 -s kümülatif run_experiment ()

0,643 saniyede 4203 işlev çağrısı

Sıralama ölçütü: kümülatif zaman

Liste, kısıtlama nedeniyle 32'den 7'ye düşürüldü < 7 > ncalls tottime percall cumtime percall dosya adı: lineno (işlev)

10.0000.0000.6430.643 < dizi > : 1 ( < modül > )

10,0010,0010,6430,643

cprof_example.py:4(run_experiment)

1000.0030.0000.5830.006 linalg.py:702(eigvals)

2000.5690.0030.5690.003

{numpy.linalg.lapack_lite.dgeev}

1000,0580,0010,0580,001 {method'randn '}

1000.0030.0000.0050.000

linalg.py:162(_assertFinite)

2000,0020,0000,0020,000 {tüm yöntem '

'numpy.ndarray'}

Benzer şekilde,% run -p -s kümülatif cprof_example.py'yi çağırmak komut satırına benzer bir etkiye sahiptir, ancak Ipython'dan ayrılmanıza gerek yoktur.

Jupyter not defterinde, tüm bir kod parçasını analiz etmek için %% budama sihri yöntemini (% iki) kullanabilirsiniz. Bu, analiz çıktısı ile ayrı bir pencere açacaktır. "Bu kod neden bu kadar uzun sürüyor?" Gibi bazı soruları hızlı bir şekilde yanıtlamak uygundur.

IPython veya Jupyter kullanarak, analizin anlaşılmasını kolaylaştıracak başka araçlar da vardır. Bunlardan biri, analiz sonuçları için etkileşimli bir görselleştirme arayüzü oluşturmak için d3.js kullanan SnakeViz'dir (https://github.com/jiffyclub/snakeviz/).

05

Satır satır analiz işlevi

Bazı durumlarda,% prun (veya cProfile'a dayalı diğer analiz yöntemleri) ile elde edilen bilgiler, işlev yürütme süresinin tamamını elde edemez veya sonuç çok karmaşıktır ve yorumlanması zor olan işlev adı eklenir. Bu durum için line_profiler adında küçük bir kitaplık vardır (PyPI veya paket yönetim araçlarıyla kullanılabilir). Bir veya birden çok işlev için kullanılabilen yeni bir% lprun sihirli işlevini etkinleştirebilen IPython eklentisini içerir.

Fonksiyon satır satır analiz edilir. Bu eklentiyi, IPython yapılandırmasını değiştirerek (bu bölümün ilerisindeki IPython belgelerine veya yapılandırma bölümüne bakın) ve aşağıdaki satırı ekleyerek etkinleştirebilirsiniz:

# Yüklenecek IPython uzantılarının noktalı modül adlarının listesi.

c.TerminalIPythonApp.extensions =

Ayrıca şu komutu da çalıştırabilirsiniz:

% load_ext line_profiler

line_profiler programlarda da kullanılabilir (tam belgelere bakın), ancak IPython'da en güçlü olanıdır. Bazı NumPy dizi işlemlerini yapmak için aşağıdaki koda sahip bir prof_mod modülünüz olduğunu varsayalım:

numpy.random import randn'dan

def add_and_sum (x, y):

eklendi = x + y

summed = added.sum (axis = 1)

özetlenen dönüş

def call_function ():

x = randn (1000, 1000)

y = randn (1000, 1000)

add_and_sum (x, y) döndür

Add_and_sum işlevini anlamak istiyorsanız,% prun şunları verebilir:

İçinde:% run prof_mod

İçinde: x = randn (3000, 3000)

İçinde: y = randn (3000, 3000)

İçinde:% prun add_and_sum (x, y)

0,049 saniyede 4 işlev çağrısı

Sipariş veren: dahili zaman

ncalls tottime percall cumtime percall

dosyaadı: lineno (işlev)

10,0360,0360,0460,046

prof_mod.py:3(add_and_sum)10,0090,0090,0090,009 {method'sum 'of

'numpy.ndarray'}

10,0030,0030,0490,049 < dizi > : 1 ( < modül > )

Yukarıdaki yaklaşım pek aydınlatıcı değil. IPython eklentisi line_profiler etkinleştirilir ve yeni% lprun komutu kullanılabilir. Kullanımdaki fark,% lprun'a hangi işlevi analiz edeceğimizi söylememiz gerektiğidir. Sözdizimi şöyledir:

% lprun -f func1 -f func2 deyimi_to_profile

Add_and_sum'u analiz etmek istiyoruz, şunu çalıştırın:

In:% lprun -f add_and_sum add_and_sum (x, y)

Zamanlayıcı birimi: 1e-06 s

Dosya: prof_mod.py

İşlev: 3. satırda add_and_sum

Toplam süre: 0.045936 s

Satır # Vuruş Başına Vuruş Süresi% Zaman Satır İçeriği

=============================================== ============

3 def add_and_sum (x,

y):

41 3651036510.079.5 eklendi = x + y

51 94259425.020.5 toplamı =

add.sum (eksen = 1)

61 11.00.0 dönüş toplamı

Bunu yorumlamak kolaydır. Kod ifadesindeki ile aynı işlevi analiz ettik. Önceki modül koduna bakarak, tam bir kod performans özeti elde etmek için call_function işlevini çağırabilir ve analiz edebilir ve add_and_sum yapabiliriz:

İçinde:% lprun -f add_and_sum -f call_function call_function ()

Zamanlayıcı birimi: 1e-06 s

Dosya: prof_mod.py

İşlev: 3. satırda add_and_sum

Toplam süre: 0.005526 s

Satır # Vuruş Başına Vuruş Süresi Yüzdesi Satır İçeriği ====================================== ======================

3 def add_and_sum (x,

y):

41 43754375.079.2 eklendi = x + y

51 11491149.020.8 toplamı =

add.sum (eksen = 1)

61 22.00.0 dönüş toplamı

Dosya: prof_mod.py

İşlev: 8. satırdaki call_function

Toplam süre: 0.121016 s

Satır # Vuruş Başına Vuruş Süresi% Zaman Satır İçeriği

=============================================== ============

8 def call_function ():

91 5716957169,047,2 x = randn (1000,

1000)

101 5830458304.048,2 y = randn (1000,

1000)

111 55435543.04.6 dönüş

add_and_sum (x, y)

Benim deneyimim makro analiz için% prun (cProfile) ve mikro analiz için% lprun (line_profiler) kullanmaktır. Her iki aracı da net bir şekilde anlamak en iyisidir.

Not:% lprun kullanılırken işlev adının belirtilmesi gerekmesinin nedeni, her satırın yürütme süresini çok fazla izlemektir. Yararsız işlevleri izlemek, sonuçları önemli ölçüde değiştirebilir.

Python öğrenme rotası ve PDF e-kitabı öğrenmek için birbirleriyle işbirliği yapar: onu elde etmenin yolu çok basit: iletilen makaleyi takip edin ve ardından editörü özel olarak yazın (öğrenin)!

Python tam aralığı

Aşama 1: Python girişi Aşama 2: Derinlemesine Python ve iyileştirme Aşama 3: Python ağı ve eşzamanlı programlama Aşama 4: Veritabanı programlama temeli Aşama 5: Linux ortamı programlama temeli Aşama 6: Python temel özellikleri Aşama 7: Web sayfası Programlamanın Temelleri Aşama 8: Python_Django Çerçevesi Aşama 9: Python_Tornado Çerçevesi Aşama 10: Python_ Büyük E-ticaret Projesi Aşama 11: Python Tarayıcı Geliştirme Aşaması 12: Başarılı İş Arama için Mülakat ve Gizli Beceriler Aşama 13: İstihdam Sonrası CTO'ya hızlı büyüme

Bunu elde etmenin yolu çok basit: iletilen makaleyi takip edin ve editöre özel olarak yazın (öğrenin)!

Retro ve havalı, nostaljik ve klasik, Baweitang klasik Bluetooth hoparlör deneyimi
önceki
Küçük boyutlu ve mükemmel işçilik, bu Baweitang klasik Bluetooth hoparlörü çok bireysel
Sonraki
İlk yarı-Borisov 1-0 Arsenal, Dragon skorları
599.000'den başlayan 2019 BMW 6 Serisi GT satışa çıktı, tüm seriler fiyatları düşürdü ve 3.0T gücü iptal etti
Tüm yönleri dinleyin, Logitech G233 oyun kulaklığı deneyimi
Çocukluk anılarını geri getirin! Baweitang Klasik Bluetooth Hoparlör Deneyimi
Tarayabilir misin? Hayır, QR koduyla oynamak farklı olacak
Python coroutine serisi (6) asyncio + tkinter geliştirme
California Fire Bull vahşileşiyor! Red Fire Bull CR1280 PRISM Full Tower RGB Oyun Kasası Derin Araştırma
Python coroutine serisi (6) -EventLoop ve Future ayrıntılı açıklama ve eşzamanlılık gerçekleştirme
Ekspres teslimat gizlilik sayfasının gözlemlenmesi: kurye el yazısıyla yazılan bilgileri doldurur, kullanıcılar bunu zahmetli bulur
Tüm insanlar tarafından paylaşılan on bin dönümlük "göl yüzeyi": Tmall Yangcheng Gölü tüylü yengeç kartı kuponları geçen yıl aynı dönemde birkaç kez arttı
Geely'nin yeni coupe SUV önizlemesi yayınlandı: yakıt tüketimi CR-V'den yalnızca 1,2 litre daha yüksek
Python coroutine serisi (üç) üzerinden verimin ayrıntılı açıklaması (Python yolu ve makalenin sonuna eklenmiş PDF)
To Top