Today’s New Year’s Eve, why not "30"? It changed to "29 years old" after a difference of one or two seconds, and it came back three years later.

The Spring Festival is approaching Shencheng with a strong flavor.
Today’s New Year’s Eve, I believe everyone is looking forward to a big dinner tonight. We have habitually called New Year’s Eve "New Year’s Eve". However, have you noticed that there is no "New Year’s Eve" this year, only "Year 29"?
In fact, this is all because our lunar calendar is "too reasonable".
Where is the New Year’s Eve?
Shi Kun, director of the Network Science Department of the Exhibition and Education Center of the Shanghai Planetarium, said that the solar calendar is the most commonly used in our life. In fact, it is more precisely the Gregorian calendar, or Gregory calendar. For example, January 1st of New Year’s Day, May 1st of Labor Day, October 1st of National Day, etc., all these festivals use the Gregorian calendar. The Gregorian calendar refers to the period of revolution-Tropic Year of the Earth, with an average of 365.2422 days a year.
The lunar calendar, on the other hand, is a combined calendar of yin and yang, and its month length is determined with reference to the apparent movement of the moon-the cycle of phase change. The moon’s cycle of "rain or shine" is called the new moon, the new moon is the new moon and the full moon is the hope, hence the name. The average length of a first lunar month is 29.5306 days (29 days, 12 hours and 44 minutes). Therefore, the number of days in the lunar month is either 30 days or 29 days, so there is a folk saying that "the big month is 30 days and the small month is 29 days". However, the arrangement of the big moon and the small moon is not arranged at regular intervals, but is completely decided by the moon phase.
We often say that "the lunar calendar is a traditional calendar in China with a history of thousands of years", but this statement is not accurate. Chinese culture has a long history, and there have been more than 100 calendars in thousands of years. The lunar calendar is only the calendar currently used, but it inherits the ancient calendars such as the summer calendar in terms of big principles and algorithms. The compilation of the lunar calendar stipulates that the first day of each month, that is, the "first day", is determined by the time when the "new moon" appears. This principle is called "the method of determining the new moon".
Accord to that compilation and promulgation of the lunar calendar drafted by Purple Mountain observatory of Chinese academy of science, "Shuori is the first lunar day of the lunar month", that is to say, the first day of each lunar month is Shuori. From "New Moon" to "Hope" and then to the next "New Moon", the period is about 29.53 days, so the calculated number of lunar months is either 29 days for a small moon or 30 days for a big moon.
Round counting, the lunar month is divided into 30 days and 29 days according to the size. If the twelfth lunar month happens to meet the lunar abortion, there will be no "New Year’s Eve".
Specifically, because it coincides with the 29-day abortion, the "New Year’s Eve" on the day before the Spring Festival of the Year of the Tiger in the upcoming lunar calendar has been "omitted".
There will be no "New Year’s Eve" in the next five years.
In fact, there are many times when the twelfth lunar month meets the abortion, and it is not uncommon for the twelfth lunar month to meet the abortion. There is no "New Year’s Eve" in the past 2013, 2016, and the next five years from 2025 to 2029.
Are there any rules?
"It is generally regular, but it seems that the regularity is not very strong locally." Shi Kun explained that it was because the moon, a satellite, was not small compared with the earth around which it revolved, so the orbit of the moon was not simple. It kept swinging, as if it were dancing a very complicated "waltz" between the earth and the moon. A lunar cycle averages 29.5306 days, but it is only average, which does not mean that every month is 29.5306 days. Similarly, the length of a lunar year may be 354 days or 355 days, which is not fixed (the probability of 354 days is higher).
If you don’t understand, imagine the extreme situation: if the new moon occurs at 23: 59, the number of days in the lunar month will be one day less; If the new moon happens at 0: 01, there will be an extra day. It is no exaggeration to say that a difference of one or two minutes can determine whether New Year’s Eve is "30" or "29".
The lunar calendar is so "reasonable", let nature decide everything!
Author: Shen Qiusha
Editor in charge: Ren Quan
* The exclusive manuscript of Wenhui, please indicate the source.
Reporting/feedback

How strong is the financial support for real estate? State-owned enterprises and private enterprises treat each other equally and support the reasonable extension of stock financing.

  According to a number of media reports, the People’s Bank of China and China Banking and Insurance Regulatory Commission recently jointly issued the Notice on Doing a Good Job in Financial Support for the Stable and Healthy Development of the Real Estate Market (hereinafter referred to as the Notice).

  On November 14th, The Paper verified from trust, insurance and other institutions that he had received the Notice.

  The "Notice" promulgated 16 financial measures to support the real estate market, involving financial institutions including commercial banks, policy banks, trust companies, insurance companies and financial asset management companies.

  State-owned and private housing enterprises are treated equally, and support the reasonable extension of stock financing such as development loans and trust loans.

  In order to keep real estate financing stable and orderly, the Notice proposes that, first, we should adhere to the principle of "two unwavering" and treat all kinds of real estate enterprises, such as state-owned and private enterprises, equally. Encourage financial institutions to focus on supporting the steady development of real estate enterprises with perfect governance, focus on their main businesses and good qualifications. Support the project sponsor bank and syndicated loan model, strengthen the management of the whole process of loan approval, issuance and recovery, and effectively ensure the safety of funds.

  The second is to support all localities to implement differentiated housing credit policies based on national policies, reasonably determine the down payment ratio of local individual housing loans and the lower limit of loan interest rate policies, and support rigid and improved housing demand.

  The third is to stabilize the credit supply of construction enterprises. Encourage financial institutions to optimize credit services for construction enterprises on the basis of controllable risks and sustainable business, provide necessary loan support, and maintain continuous and stable financing for construction enterprises.

  Fourth, support the reasonable extension of stock financing such as development loans and trust loans. For stock financing such as development loans and trust loans of real estate enterprises, under the premise of ensuring the security of creditor’s rights, financial institutions and real estate enterprises are encouraged to negotiate independently on the basis of commercial principles, and actively support them by extending the stock loans and adjusting repayment arrangements to promote the completion and delivery of projects. As of the date of issuance of this notice,Due in the next six months, it can be extended for one year beyond the original provisions, without adjusting the loan classification.The loan classification submitted to the credit information system is consistent with it.

  The fifth is to keep bond financing basically stable. Support high-quality real estate enterprises to issue bonds for financing. Promote professional credit enhancement institutions to provide credit enhancement support for the bond issuance of real estate enterprises with overall financial health and short-term difficulties. Encourage bond issuers and holders to communicate in advance and make arrangements for bond redemption funds. If it is indeed difficult to pay on schedule, reasonable arrangements such as extension and replacement shall be made through consultation to actively resolve risks. Support bond issuers to buy back bonds in domestic and foreign markets.

  The sixth is to maintain the financing stability of asset management products such as trusts.Encourage trust and other asset management products to support the reasonable financing needs of real estate.. Encourage financial institutions such as trust companies to speed up business transformation, support the reasonable financing needs of real estate enterprises and projects according to the principles of marketization and rule of law on the basis of strictly implementing the regulatory requirements for asset management products and doing a good job in risk prevention and control, and provide financial support for real estate enterprise project mergers and acquisitions, commercial pension real estate, rental housing construction, etc. according to laws and regulations.

  Actively do a good job in the financial services of "guaranteed delivery building" and support relevant banks to add supporting financing support.

  As for the financial services of Baojiaolou, the Notice proposes to support China Development Bank and Agricultural Development Bank to issue special loans of Baojiaolou to borrowers who have been reviewed and filed in compliance with the law, efficiently and orderly in accordance with relevant policy arrangements and requirements, with closed operation and special funds earmarked for supporting the accelerated construction and delivery of sold overdue residential projects.

  After the special loan support project clarifies the creditor’s rights and debts, the special loan and the new judicial guarantee for supporting financing, financial institutions, especially the main financing commercial bank of the project personal housing loan or its leading syndicates, are encouraged to follow the principles of marketization and rule of law.Provide new supporting financing support for special loan support projects.To promote the resolution of the risk of personal housing loans that have not been handed over.

  Actively cooperate with the risk disposal of trapped real estate enterprises and actively explore market-oriented support methods.

  "Notice" said that it is necessary to do a good job in financial support for real estate project mergers and acquisitions and actively explore market-oriented support methods. Encourage commercial banks to carry out M&A loan business for real estate projects in a steady and orderly manner, and focus on supporting high-quality real estate enterprises to merge and acquire troubled real estate enterprise projects. Encourage financial asset management companies and local asset management companies (hereinafter referred to as asset management companies) to give full play to their experience and ability in the disposal of non-performing assets and risk management, and consult with local governments, commercial banks, real estate enterprises, etc. on risk resolution models to promote the accelerated disposal of assets. Encourage asset management companies to cooperate with third-party institutions such as law firms and accounting firms to improve the efficiency of asset disposal. Support qualified commercial banks and financial asset management companies to issue real estate project M&A themed financial bonds.

  For some projects that have entered the judicial reorganization, financial institutions can help promote the project to return to work and deliver according to the principles of independent decision-making, self-risk and self-financing. Encourage asset management companies to participate in project disposal by acting as bankruptcy administrators and reorganizing investors. Support qualified financial institutions to steadily explore ways to solve the risks of trapped real estate enterprises in accordance with laws and regulations by setting up funds, and support the completion and delivery of projects.

  Protect the legitimate rights and interests of housing finance consumers and personal credit rights and interests according to law.

  The "Notice" emphasizes encouraging independent negotiation in accordance with the law to postpone the repayment of principal and interest, and effectively protecting the personal credit rights of deferred loans. Specifically, for individuals who are hospitalized or isolated due to the epidemic, or who have lost their sources of income due to the suspension of business and unemployment due to the epidemic, and personal housing loans that have been changed or cancelled due to the purchase contract, financial institutions can independently negotiate with the buyers according to the principles of marketization and rule of law, and make adjustments such as extension. All parties concerned must abide by the rules, abide by the contract and fulfill their commitments. In this process, financial institutions should do a good job in customer service, strengthen communication, protect the legitimate rights and interests of financial consumers according to law, and classify assets according to relevant regulations. Acts of malicious evasion of financial debts shall be dealt with according to laws and regulations to maintain a good market order.

  In terms of personal credit rights, if the repayment arrangement of personal housing loans has been adjusted, financial institutions shall submit credit records according to the new repayment arrangement; If it is determined by the judgment or ruling of the people’s court that it should be adjusted, the financial institution shall adjust the credit records according to the effective judgment or ruling of the people’s court, and adjust those that have been submitted. Financial institutions should properly handle relevant credit objections and protect the rights and interests of information subjects according to law.

  Adjust some financial management policies in stages to accelerate the marketization of real estate risks.

  According to the Notice,Extend the transition period arrangement of real estate loan concentration management policy and optimize the financing policy of real estate project M&A in stages.. For banking financial institutions that can’t meet the requirements of real estate loan concentration management as scheduled due to objective reasons such as epidemic situation, the People’s Bank of China, China Banking and Insurance Regulatory Commission or branches of the People’s Bank of China, and China Banking and Insurance Regulatory Commission dispatched offices will reasonably extend their transition period according to the relevant provisions on the management of real estate loan concentration, based on the actual situation and through objective evaluation.

  At the same time, relevant financial institutions should make good use of the staged real estate financial management policies that have been promulgated by the People’s Bank of China and China Banking and Insurance Regulatory Commission, which are applicable to major commercial banks and national financial asset management companies, and accelerate the market-oriented clearing of real estate risks.

  Increase financial support for housing leasing and broaden diversified financing channels in relevant markets.

  The "Notice" proposes to optimize housing rental credit services and broaden diversified financing channels in the housing rental market. Guide financial institutions to focus on increasing credit support for self-sustaining property-based housing leasing enterprises with independent legal person operation, clear business boundaries and real estate professional investment and management capabilities, rationally design loan terms, interest rates and repayment methods, and actively meet the medium and long-term capital needs of enterprises. Encourage financial institutions to provide financial support for various entities to purchase and rebuild real estate projects for housing leasing in accordance with the principles of marketization and rule of law. Loans issued by commercial banks to affordable rental housing projects that hold the confirmation of affordable housing rental projects are not included in the concentration management of real estate loans. Commercial real estate is transformed into affordable rental housing, and after obtaining the confirmation of affordable rental housing, the bank’s loan term and interest rate are applicable to the relevant policies of affordable rental loans.

  At the same time, support housing leasing enterprises to issue direct financing products such as credit bonds and guarantee bonds, which are specially used for the construction and operation of rental housing. Encourage commercial banks to issue financial bonds to support housing leasing, and raise funds to increase the development and construction loans and operating loans for housing leasing. Steadily promote the real estate investment trust funds (REITs) pilot.

Renew the contract at the same time! Poole is 140 million in 4 years, Wiggins is 109 million in 4 years, and next year, the salary of Warriors will break 500 million!

On October 16th, Beijing time, according to the latest report of the NBA’s famous Woshen, Golden State Warriors reached a contract renewal agreement with Poole and Wiggins at the same time. Poole signed a four-year contract of $140 million, while Wiggins significantly reduced his salary and signed a four-year contract of $109 million. Golden State Warriors spent $249 million to keep Poole and Wiggins at the same time, which is undoubtedly a huge surprise for Golden State Warriors’ road to championship in the next few years!

After the news of the famous God Woshen broke the news, according to several ESPN sources, Golden State Warriors and Jordan Poole formally reached a four-year and $140 million early contract renewal agreement. The guaranteed amount of the contract is USD 123 million, with an incentive clause. After the incentive clause is completed, the contract amount can be expanded to 140 million.

Jordan Poole was selected by Golden State Warriors with the 28th overall pick in the first round of the 2019 draft, and then signed a four-year, $10.09 million rookie contract with the Warriors. At present, there is one year left in the rookie contract, which is worth $3.9 million. The new contract will not take effect until the 2023-24 season. 2? In the 2001-22 regular season, Poole played 30 minutes per game with 18.5 points, 3.4 rebounds, 4 assists and 0.8 steals. In the playoffs, he played 27.5 minutes per game with 17.0 points, 2.8 rebounds, 3.8 assists and 0.8 steals.

Subsequently, the American media StatMuse exposed a set of data, ranking the top six in the average annual salary of 2019 rookie’s early contract renewal, and Morant, Zion and Garland’s average annual salary was $38.86 million, which tied for the top three. Poole’s average annual salary after renewal is as high as $35 million, ranking fourth, followed by Hiro’s average annual salary of $30 million and Barrett’s average annual salary of $26.79 million.

At the same time, after Poole’s 4-year contract extension of $140 million, Golden State Warriors will have four players with annual salary exceeding $28 million in 2023-24 season, and these four players are rookies cultivated by Golden State Warriors themselves: Curry’s annual salary is $52 million, Clay’s annual salary is $43 million, Poole’s annual salary is $35 million, and Chasing Dreams Green’s annual salary is $28 million. The success rate of rookie like Golden State can be said to be the only one in the league.

In addition, according to the famous story of God Wo, Golden State Warriors renewed their contract with All-Star Wiggins for four years, with a contract value of 109 million dollars. Wiggins will be tied with Golden State Warriors for five years, with a total contract value of 143 million dollars. Mouth Wiggins earned $33.6 million this season. The salary of the new contract will be reduced to $24.3 million in the first year and $26.3 million in the second year. Golden State Warriors gave Mouth Wiggins the option in the last year.

Kou Wiggins was the No.1 draft pick in 2014. On the day he was selected, he was traded to Timberwolves by Cavaliers. He stayed there for six years until he was traded to Golden State Warriors in 2020. In the 2021-22 season, Wiggins played the masterpiece of his career, averaging 17.2 points, 4.5 rebounds and 2.2 assists per game. He was selected as an NBA All-Star for the first time.

Wiggins’ performance in the playoffs was even more amazing, averaging 16.5 points, 7.5 rebounds and 1.8 assists per game, with a shooting percentage of 46.9%, a 3-point shooting percentage of 33.3% and a free throw percentage of 64.6%. His performance was comprehensive and stable. Wiggins’ total positive and negative value in the playoffs is as high as +140, which is superior to all playoff players, even higher than Curry, ranking first in the league!

After learning that Poole renewed the Golden State Warriors for $140 million in four years, many experts and fans thought Wiggins would leave, but Wiggins chose to reduce his salary by nearly $10 million a year and renew the Golden State Warriors. We have to sigh, Wiggins is sure to be true love to Golden State Warriors, but Golden State Warriors are like many media descriptions to Wiggins, like breaking a bone and getting a big bargain!

In the past season, Poole and Wiggins both played the most time in Golden State Warriors, Wiggins played 2,329 minutes, Poole played 2,283 minutes, which shows their importance to Golden State Warriors. Golden State Warriors stayed with $249 million. Wiggins, 27, and Poole, 23, when Curry, Clay, and Dream Chasing are all getting old, the successors of Golden State Warriors, have quietly taken their place.

The Golden State Warriors dropped $249 million and renewed Poole and Wiggins at the same time. We also have to admire the courage of Lakob, the owner of Golden State Warriors. Because, according to the analysis of salary expert Bobby Marks, if Dream Pursuit chooses to implement the option of 27.6 million players in 23-24 season, the total salary of 12 players in Golden State Warriors in 23-24 season will reach 215 million, and the luxury tax will reach 268 million, totaling 483 million. Once there are 14 full players, the total salary and luxury tax will probably exceed 500 million dollars.

Marcus Thompson II, the team reporter of Golden State, published the salary details of Golden State Warriors in the 23-24 season, which confirmed the above statement: Curry 51.9 million, Clay 43.2 million, Poole 28 million (estimated), dream-chasing: 27.6 million (if the player option is implemented), Wiggins 24.3 million, Wiseman 12.1 million, Rooney 7.5 million and Kuminga 60.

If the 14-member roster is completed, the luxury tax that Golden State Warriors will have to pay in 2023-2024 will exceed $275 million, which is higher than the combined salaries of Knicks and Grizzlies this year. As we all know, Lakob, the owner of Golden State Warriors, only spent 450 million dollars when he acquired Golden State Warriors in 2010. The total salary next year will exceed the total value of the team that year. Lakob is really rich and willful!

After renewing Poole and Wiggins at the same time, the salary space of Golden State Warriors can be said to be an unprecedented explosion! What about the next dream catcher Green who is facing a contract renewal? Referring to the first year after the renewal of the contract, the annual salary of Brother Wilkins will be reduced to 24.3 million USD. Dreamcatcher Green must reduce his salary if he wants to stay in Golden State for a long time!

I put the essence of Python coroutine Pa was clean!

This article is a large amount of information, from IO multiplexing, to use the generator, then async, await realization of the principle behind it, in simple terms, the analysis was very thorough, very hardcore!

Two days for personal reasons because it did not touch a long time to write a point of Python, which involves "coroutine" program, the last time out, it is Web framework tornado unique feature, now we have async, await keyword support . Thought about its implementation, reviews the evolution of these years, feel a little bit mean.

They are single-threaded, why the original code with the low efficiency of the async, await add some asynchronous library becomes higher efficiency?

They are single-threaded, why the original code with the low efficiency of the async, await add some asynchronous library becomes higher efficiency?

If you do Python-based network or Web development, this question has puzzled, this article attempts to give an answer.

Before beginning 0x00

Firstly, Not take you browse the source codeAnd then tell you the control to achieve the original code Python standard. Instead, we will set out from the real problems, think of solutions to the problem, step by step evolution path experience solutions, and most importantly, hoping to gain knowledge in a systematic upgrade process.

This article only provides an independent direction of thinking, does not follow the historical and current actual implementation details.

Secondly, you need to read this article familiar with Python, at least understand the concept generator generator of Python.

0x01 IO multiplexing

This is the key to performance. But we are here only to explain the concept, its implementation details is not the point, which we understand Python coroutine enough, as already know enough about, advances to 0x02.

First, you want to know all the network service program is a huge loop, your business logic can be called at some point in this cycle:

defhandler (request):

WHILETRUE:

# Get a new request

request=accept

# To get users to write business logic function according to the route map

Handler=GET_HANDLER (Request)

Handler (Request)

Imagine your Web service of a handler, after receiving a request requires a response to the results of API calls.

For the most traditional network applications, your API requests issued to wait for a response after this time the program stops running, even new requests have to get in after the end of the response. If you rely on an API request packet loss seriously, especially in response to slow it? That will be very low throughput applications.

Many traditional Web server using multi-threading technology to solve this problem: the run handler is placed on other threads, each dealing with a request, this does not affect the new thread blocks request to enter. This problem can be solved to some extent, but for larger systems concurrent, multithreaded scheduling will bring significant performance overhead.

IO multiplexing can be done to solve the problem without the use of threads, it is provided by the operating system kernel functions, we can say specifically for this type of scenario for us. Simply put, your program encounters network IO, tells the operating system to help you staring at, while the operating system gives you a way to make you can feel free to get what IO operation has been completed. like this:

# # 操作 系统 复 复 示 示 例 代代

# Register the ID and type of IO operations to the operating system IO

IO_REGISTER (IO_ID, IO_TYPE)

# Get completed IO operations

Events=IO_GET_FINISHED

For (IO_ID, IO_TYPE) INEvents:

IFIO_TYPE==Read:

Data=read_data (IO_ID)

Elifio_Type==Write:

Write_data (IO_ID, DATA)

Gring the IO multiplex logic into our server, probably like this:

Call_backs={}

Defhandler (REQ):

# do jobs here

DefCall_back (Result):

# Use the returned Result to complete the remaining work …

Call_backs [IO_ID]=CALL_BACK

# New cycle

WHILETRUE:

# Get the completed IO event

IFIO_TYPE==Read: # read

Data=read (IO_ID)

Call_back=call_backs [io_id]

Call_back (data)

Else:

# Other types of IO event processing

PASS

# Get a new request

Handler (Request)

Our Handler has returned immediately for the IO operation. At the same time, each iteration will perform a callback over the completed IO, the network request no longer blocks the entire server.

The pseudo code above is only for understanding, and the details are more complicated. Moreover, it is also possible to connect the new request to the IO event from the operating system to the monitor port.

If we split the cycle part with a call_backs dictionary to a separate module, we can get an EventLoop, which is the iOLOOP provided in the Python Standard Library Asynci.

0x02 with generator to eliminate Callback

He focuses on the Handler function written in our business, after having independent iOLOOP, it now becomes like this:

# 业 业 代 代 … …

# Need an API request

Print (Result)

ask_LOOP.GET_EVENT_LOOP.IO_CALL (API, CALL_BACK)

Here, performance problems have been resolved: We no longer need multi-threads to constantly accept new requests in the source, and don’t have to rely on the API response.

But we have also introduced a new problem. The original business logic code is now demolished. The code before requesting the API is still normal. The code after the request API can only be written in the callback function.

Here our business logic has only one API call. If there are multiple APIs, plus the call to Redis or MySQL (their essential is also a network request), the entire logic will be split, this is a burden on business development .

For some languages ??with anonymous functions (right is Java), it may also trigger a so-called "turning hell".

Next, we find way to solve this problem.

We can easily think that if the function can be suspended after running to the network IO operation, it will wake up at the breakpoint after completion.

If you are familiar with Python’s "Builder", you should find that it happens to have this feature:

Defexample:

Value=yield2

Print ("Get", Value)

ReturnValue

g=esample

# 启 启 生器, we will get 2

Got=G.send (NONE)

Print (got) # 2

TRY:

# Anti-start will display "get 4", which is our incoming value

Got=g.send (got * 2)

ExceptStopItemization ASE:

# Builder runs, will print (4), E.Value is the value of generator return

Print (E.Value)

There is Yield keyword in the function, and the call function will get a generator, and a key method for generator can interact with the generator.

G.send (none) runs the generator code until you encounter Yield, and return to the object, that is, 2, the generator code is stopped here until we perform G.send (got * 2) again, The 2 * 2 is also 4 to assign the value Value in front of Yield, and then continue to run the generator code.

Yield is like a door, you can send a thing from here, you can also take another thing.

If Send makes the generator to run until the next yield is over, the Send call will trigger a special exception STOPITERATION, which comes with a property Value, which is the value of the generator Return.

If we convert our Handler to a generator with Yield keyword, run it to The specific content of IO operationReturns, put the IO result back and restore the generator to run, then solve the problem of uncomfortable business code:

# 业 业 代 代 … …

# Need to execute an API request, directly put the IO request information yield

Result=yieldio_info

# Use the result returned by the API to complete the remaining work

Print (Result)

# This function is registered in iOLOOP, used to call back when there is a new request

Defon_Request (request):

Handler=GET_HANDLER (Request)

g=Handler (Request)

# 首 首 启 获得 获得 i 获得

IO_INFO=G.send (none)

g.send (Result)

ask_LOOP.GET_EVENT_LOOP.IO_CALL (IO_INFO, CALL_BACK)

The above example, the Handler code written by the user will not be dispersed into the callback, and the ON_Request function interacts with Callback and IOLOOP, but it will be implemented in the web framework, which is not visible to the user.

The above code is enough to give us inspiration of Callback destroyed with the builder, but there are two points:

  1. Only a network IO is initiated in business logic, but it is often more

  2. Business logic does not call other asynchronous functions (helping), but in practice, we tend to call other levels.

Let’s take a more complex example:

Among them, Request executes real IO, FUNC1, FUNC2 is only called. Obviously our code can only be written:

Deffunc1:

Ret=yieldfunc2 (re)

returnret

Deffunc2 (DATA):

ReturnResult

DEFREQUEST (URL):

# This simulation returns an IO operation, contains all information about the IO operation, where the string is simplified

Result=yield "IOJOB OF% S"% URL

ReturnResult

For Request, we expose the IO operation to the framework through Yield.

for Func1 and func2, calling request, clearly add Yield keywords Otherwise, the request call returns a generator and will not be paused and continue to perform subsequent logic obviously errors.

This is basically that we don’t write asynchronous code in the Tornado framework without Yield from, Aysnc, AWAIT.

To run the entire calling stack, the approximate process is as follows:

  1. Call FUNC1 to get the generator

  2. Call Send (None) Start it gets the result of request ("http://test.com/foo"), or generator object

  3. Send (none) Starts the generator generated by the request, gets the IO operation, registered by the frame to IOLOOP and specify a callback

  4. The Request Builder wakes up in the callback function after IO, and the generator will go to the return statement end

  5. Capture an exception to get the return value of the Request Builder, wake up the last layer of FUNC1, and get a FUNC2 generator

  6. Continue to execute …

Call FUNC1 to get the generator

Call Send (None) Start it gets the result of request ("http://test.com/foo"), or generator object

Send (none) Starts the generator generated by the request, gets the IO operation, registered by the frame to IOLOOP and specify a callback

The Request Builder wakes up in the callback function after IO, and the generator will go to the return statement end

Capture an exception to get the return value of the Request Builder, wake up the last layer of FUNC1, and get a FUNC2 generator

Continue to execute …

Friends who are familiar with the algorithm and data structure encounter such a traversal logic that will be returned, can be recursively used, because the recursive use generator can not do it, we can use the stack, in fact, this is the word "call stack" origin.

With the stack, we can Connect all generators connected in series in the entire call chain to a generatorFor its constant Send, you can continue to get all IO operation information and drive the call chain advancement, and the implementation method is as follows:

  1. The first generator is in the stack

  2. Call the Send, if you get the generator, you will enter the next round iteration

  3. I encountered IO to ask Yield, let the frame sign up to iOLOOP

  4. After the IO operation is completed, the cache result is forth, enter the next round iteration, the purpose is to restore the upper function using IO results.

  5. If a generator is running, you also need to restore the upper function to the upper function.

The first generator is in the stack

Call the Send, if you get the generator, you will enter the next round iteration

I encountered IO to ask Yield, let the frame sign up to iOLOOP

After the IO operation is completed, the cache result is forth, enter the next round iteration, the purpose is to restore the upper function using IO results.

If a generator is running, you also need to restore the upper function to the upper function.

If implemented, the code is not long but the amount of information is relatively large.

It turns the entire call chain to a generator, calling the send, to complete the IO in the chain, complete these IO, continue to push the logic execution in the calling chain until the overall logic ends:

DEFWrapper (GEN):

# The first layer calls the stack

Stack=stack

Stack.push (gen)

# Start a layer-by-layer call

WHILETRUE:

# Get the top elements of the stack

item=stack.peak

Result=none

IFisgenerator (item):

TRY:

# Try to get the next layer call and get it in the stack

Child=item.send (Result)

Stack.push (child)

# Result Restore to NONE

Result=none

# After entering the stack, enter the next loop directly, continue to explore down

Continue

# If you have an end, you will temporarily save the Result, the next step to make yourself out.

Result=E.Value

Else: # o o operation

# # I 操作 操作, Yield, Io will be woken up and temporarily saved after IO

Result=yieldItem

# 走 到 here, this layer has been completed, out of the stack, the next iteration will be a layer of calling chain

Stack.pop

# 没有有 上, the entire call chain is completed, return

Ifstack.empty:

Print ("finished")

ReturnResult

This may be the most complicated part. If you look hard, it is actually as long as you understand that for the call chain in the example above, it can achieve the effect as follows:

W=Wrapper (Func1)

# Will get "IOJOB of http://test.com/foo"

W.send (none)

# 上 上 ojob foo completed the result "bar" incompart, continue to run, get "IOJOB OF http://test.com/bar"

W.send ("bar")

# 上 上 i i b 完成 完成 传 传 传 传 入 入 入 入 入 入 入 入 入 入 入 入 入

W.send ("BARZ")

With this part, the frame will be added to the matching code:

# Maintain a list of ready lists, store all completed IO events, format is (Wrapper, Result)

Ready=

# After using the wrapper package, you can process IO by Send.

g=wrapper (func1)

# Take the start state directly as the result of NONE

Ready.Append ((g, none))

# Let the iOLOOP perform this function each cycle to handle the ready for IO

Ready.Append ((g, result))

# Traversing all already generators, advance it down

Forg, Result InselF.Ready:

# Use the Result to wake the builder and get the next IO operation

IO_JOB=G.send (Result)

# After the IO operation is complete, add the generator to the ready list, wait for the next round of processing.

ask_LOOP.GET_EVENT_LOOP.IO_CALL (

IO_JOB, LambdareSult: Ready.Append ((g, result)

Here, the core idea is to maintain a list of ready-to-read, and IOLOOP is overwhelmed, and the generator that promotes the ready state is run down, and the new IO operation is registered. After the IO is completed, the ready, after several rounds of Ioloop iteration A Handler will eventually be executed.

At this point, we use the generator to write to write business logic to run normally.

0x04 Improved Scalability

If you can read it here, Python’s scope is basically clear.

We have already achieved one Miniature sweeping frameworkThe realization details of the standard library look great here, but the specific ideas are consistent.

Our equilation framework has a restriction, we can only use IO to operate asynchronously, although in the world of network programming and web programming, the block is basically only IO operation, but there are some exceptions, such as I want the current operation Sleep for a few seconds. The use of time.sleep will make the entire thread to block, requiring special implementation. For example, some CPU-intensive operations can be asynchronously through multi-threaded asynchronous, so that another thread notification event has been completed and followed.

Therefore, it is best to decouple an open space with the network, so that the network IO is only one of the scenes, improves the scalability.

The Python official solution is to let the user hand to block the block code. As for the IOLOOP to register IO event or open a thread completely by yourself, and provide a standard "placeholder" FUTURE, indicating that his results wait for the future Yes, some prototypes are as follows:

ClassFuture:

# Set the result

Defset_Result (Result): Pass

# 获取 结果 结果

Defresult: Pass

# 表示 表示 This Future object is not already set up.

Defdone: Pass

# Set the callback function that should be executed when he is set, you can set multiple

Defadd_done_callback (Callback): Pass

Our slight change can support Future, making the scalability stronger. Network request functions for user code:

# 现在 r es es,, 生 生 器 器 器 器 器 器 器 器

#future is understood as a placeholder

Fut=future

Defcallback (Result):

# Assign the placeholder when the network IO completed the callback

Fut.set_Result (Result)

ask_LOOP.GET_EVENT_LOOP.IO_CALL (URL, CALLBACK)

Now, Request is no longer a generator, but directly returns Future.

And for the function of processing the ready list in the frame:

DEFCALLBACK (FUT):

#future is set to be placed in the ready list

Ready.Append ((g, fut.result))

Fut=g.send (Result)

Fut.add_done_callback (callback)

0x05 development and change

Many years ago, when using Tornado, probably only one Yield keyword is available, the sweeper wants to achieve, that is, this idea, even Yield keywords and return keywords can not appear in a function, you want to run after the generator Returns a value, you need to manually Raise an exception, although the effect is the same as Return now, but it is still very awkward, not elegant.

Later, there was Yield from expression. What can it do?

It is popular, it is done what the generator Wrapper is doing the above: Calling link through the stack, it is the syntax of the Wrapper logic.

With it, the same example you can write:

Deffunc1:

# Note Yield from

Ret=yieldFromRequest ("http://test.com/foo")

# Note Yield from

Ret=yieldfromfunc2 (re)

returnret

Deffunc2 (DATA):

# Note Yield from

Result=yieldfromRequest ("http://test.com/"+data)

ReturnResult

# 同 上 上 实 实 实 实 实 r

Then you no longer need the brainless Wrapper function:

g=func1

# Return the first request for Future

g.send (none)

# Continue to run, automatically enter FUNC2 and get the FUTURE inside it

G.send ("bar")

# Continue to run, complete the residual logic of the call chain, throw the stopiteration exception

G.send ("BARZ")

Yield from the entire call chain directly, it is already great, but it is used asynchronous programming or otherwise, and other languages ??have special-top Async, the AWAIT keyword, until the later version puts these content With dedicated Async, AWAIT keyword packaging, it is a more elegant look today.

0x06 summary and comparison

Overall, Python’s native and trip is achieved from two aspects:

  1. Based on IO multiplexing technology, the entire application is non-blocking on IO, achieving high efficiency

  2. Change the dispersed Callback code through the generator into synchronous code, reducing business writing difficulties

Based on IO multiplexing technology, the entire application is non-blocking on IO, achieving high efficiency

Change the dispersed Callback code through the generator into synchronous code, reducing business writing difficulties

There is a language of the object of the generator. Its IO fight is achieved, the evolution of the Java fight is basically exactly, the keyword is the same, and the Future class is the same than the promise.

However, it is different for this, which is different from this sweeping with the degree of GO-named GO, and does not explicitly based on the generator.

If the class ratio, you can implement the geventime of Python, which is the runtime, and Patch off the system calls to access your own Runtime, you come to the scheduling sweeper, gevent is focused on the network, based on network IO scheduling, relatively simple, The GO achieves perfect multi-core support, more complex and perfect, and creates a new CHANNEL new programming paradigm.

Author: Mao bean peanut

Getting Started: The Most Complete Zero-Basic Python Problem | Zero-Based 8 Months Python | Battle Project | Learning Python is this shortcut

Dry goods: crawling Douban short comment, movie "later we" | 38 years old NBA best player analysis | From Wanzhong to Word! Tang Dynasty 3 disappointment | Laughing to see the new Eti Dragon Slay Dollar | Running Question King | Make a massive Miss in Python Sketch | Disc, I am so fire, I use machine to learn to be a mini recommended system movie

Fun: Poultry Game | Nine Mao Hai | Beautiful Flower | Two-Article Python "Everyday Cool" game!

AI: Robot that will be poetry | Give the picture color | predictive income | Solver, I use the machine to learn to be a mini recommended system movie

Gadget: PDF to Word, easy to get forms and watermarks! | One button saves the HTML page as PDF! Goodbye PDF to extract charges! Use 90 lines of code to create the strongest PDF converter, Word, PPT, Excel, Markdown, HTML one-to-date conversion | Make a staple low-cost ticket prompt! | 60 lines of code made a voice wallpaper switch every day to see a little sister! |

Annual explosion case

  • 1). Lying! PDF to Word Use Python to easily get it!
  • 2) Learn Python is really fragrant! I made a website with 100 lines of code, helping people PS travel pictures, earn a chicken leg to eat
  • 3). The first broadcast over 100 million, hot all net, I analyzed the "Sister Taking Wind and Waves" and found these secrets
  • 4) 80 lines of code! Do a Dream in Python with Python
  • 5). You must master the 20 Python code, short and delicate, useless
  • 6). 30 python hambo skills
  • 7). I summarized 80 "rookie Python selection dry goods.pdf", all dry goods
  • 8). Goodbye Python! I want to learn Go! 2500 word depth analysis!
  • 9). Find a dog welfare! This Python reptile artifact is too cool, automatically download the girl picture