import random as r; r.seed(1337); " ".join([f'{b:02x}' for b in r.randbytes(20)])Wynik:
'03 0d 25 9e 7b e3 ef ec a5 17 84 88 cd b1 ba b5 ff 3c a8 5d'
ekstaza, geniusz, przebłysk, olśnienie, półprawdy, półśrodki, przemilczenia, zaćmienia, głupstwa, kłamstewka, oszustwa, hultajstwo, wyrachowanie, nieprawda, nieobiektywność, niepodważalna prawda, nierówność, nieomylność, słuszność, perfekcja, krnąbrność ... niegodziwość
import random as r; r.seed(1337); " ".join([f'{b:02x}' for b in r.randbytes(20)])Wynik:
'03 0d 25 9e 7b e3 ef ec a5 17 84 88 cd b1 ba b5 ff 3c a8 5d'
import asyncio async def short_task(): print('short_task before') await asyncio.sleep(2) print('short_task after') async def print_task(): print('print_task') async def long_task(): print('long_task before') await asyncio.sleep(5) print('long_task after') async def draw_task(): print('draw_task') def main(): loop = asyncio.get_event_loop() loop.create_task(print_task()) loop.create_task(long_task()) loop.run_until_complete(short_task()) loop.run_until_complete(draw_task()) loop.close() if __name__ == '__main__': main()Program czeka aż zakończą się dwa zadania: short_task i draw_task, wcześniej uruchamiająć long_task. Ponieważ short_task i draw_task kończą się szybciej dostajemy ostrzeżenie, o wciąż działającym long_taks.
print_task long_task before short_task before short_task after draw_task Task was destroyed but it is pending! task: <Task pending coro=<long_task() done, defined at /home/beru/python_asyncio/run_until.py:13> wait_for=<Future pending cb=[<TaskWakeupMethWrapper object at 0x7f47d9b217d0>()]>>Bardziej zaawansowany przykład serwera/czatu. Tutaj mamy do czynienia z trzema rodzajami zdarzeń: uruchomienie serwera (otwarcie portów i nasłuchiwanie), oczekiwanie na tekst na stdio oraz oczekiwanie na nadejście wiadomości od klienta. Samo oczekiwanie na tekst składa się z dwóch zdarzeń: pojawienie się tekstu na stdio i zapisanie go do kolejki, oraz odczytanie, gdy coś w tej kolejce się znajduje.
import sys import asyncio def main(): queue = asyncio.Queue() loop = asyncio.get_event_loop() # Start monitoring the fd file descriptor for read availability and invoke # callback with the specified arguments once fd is available for reading loop.add_reader(sys.stdin, got_stdin_data, queue) fut = loop.create_future() fut.add_done_callback(cancel_all_task) coro = loop.create_server(lambda: Chat(loop, queue, fut), '127.0.0.1', 7777) server = loop.run_until_complete(coro) # Run until Ctrl+C is pressed or loop is stopped try: loop.run_forever() except KeyboardInterrupt: print('[+] Keyboard exception') cancel_all_task() # Stop server. Closing listening sockets it's done asynchronously, so # wait_closed() need to be used to ensure. server.close() loop.run_until_complete(server.wait_closed()) loop.close() def got_stdin_data(queue): loop = asyncio.get_event_loop() loop.create_task(queue.put(sys.stdin.readline())) def cancel_all_task(result=None): print('[+] Cancel all tasks') loop = asyncio.get_event_loop() for task in asyncio.Task.all_tasks(): task.cancel() loop.create_task(stop_loop()) async def stop_loop(): print('[+] Stop loop') loop = asyncio.get_event_loop() loop.stop() class Chat(asyncio.Protocol): def __init__(self, loop, queue, fut): self.loop = loop self.queue = queue self.fut = fut def connection_made(self, transport): peername = transport.get_extra_info('peername') print('[+] Connection from:', peername) self.transport = transport self.loop.create_task(self._wait_for_stdin_data()) def connection_lost(self, exc): print('[+] Connection lost') self.fut.set_result(True) def data_received(self, data): message = data.decode() print('[+] Data received: {!r}'.format(message)) if message.strip() == "exit": self.fut.set_result(True) def _send_reply(self, reply): print('[+] Data send: {!r}'.format(reply)) self.transport.write(reply.encode()) self.loop.create_task(self._wait_for_stdin_data()) async def _wait_for_stdin_data(self): reply = await self.queue.get() self._send_reply(reply) if __name__ == '__main__': main()W celu połączenia się z serwerm:
nc 127.0.0.1 7777Działanie:
[+] Connection from: ('127.0.0.1', 45260) [+] Data received: 'asdf\n' [+] Data received: 'exit\n' [+] Cancel all tasks [+] Stop loop
# Katalog roboczy mkdir ~/opencv_workspace cd ~/opencv_workspace git clone https://github.com/opencv/opencv.git git clone https://github.com/opencv/opencv_contrib.git # Instalacja virualenv dla Python-a. Przyda się numpy i scipy virtualenv -p python3 venv source venv/bin/activate pip install numpy pip install scipy # Konfiguracja za pomocą CMake. # Wszystko co potrzebne do budowania znajdzie się w katalogu build, # a zainstalowane zostanie do katalogu $VIRTUAL_ENV/local/ cd opencv mkdir build cmake -B build/ -D CMAKE_BUILD_TYPE=Debug \ -D OPENCV_EXTRA_MODULES_PATH=../opencv_contrib/modules/ \ -D CMAKE_INSTALL_PREFIX=$VIRTUAL_ENV/local/ \ -D PYTHON_EXECUTABLE=$VIRTUAL_ENV/bin/python \ -D PYTHON_PACKAGES_PATH=$VIRTUAL_ENV/lib/python3.7/site-packages \ -D INSTALL_PYTHON_EXAMPLES=ON # Kompilacja i instalacja (do katalogu $VIRTUAL_ENV/local/) cd build make -j4 make installPrzykładowy program
#include <opencv2/opencv.hpp> #include <iostream> int main() { cv::Mat grayImg = cv::imread("color.png", cv::IMREAD_GRAYSCALE); cv::imwrite("gray.png", grayImg); }Kompilacja:
cd ~/opencv_workspace g++ -I./venv/local/include/opencv4 -L./venv/local/lib -Wl,-rpath=./venv/local/lib \ main.cpp \ -lopencv_core \ -lopencv_imgcodecs \ -lopencv_imgprocWynik:
#include <iostream> #include <numeric> #include <execution> #include <vector> using namespace std; int main() { vector<int> vec{1, 2, 3, 4}; int result = std::reduce(std::execution::par, begin(vec), end(vec)); cout << result << endl; }W przypadku gcc (9.2.1 20191008) wymagane było zainstalowanie dodatkowej paczki libtbb-dev (Threading Building Blocks).
$ sudo apt-get install libtbb-dev $ g++ -std=c++17 main.cpp -ltbb $ ./a.out 10
// Dla std::atomic<int> x{0}; // Operacje: ++x; // atomowy pre-increment x++; // atomowy post-increment x += 1; // atomowy increment int y = x * 2; // atomowy odczyt x x = y + 2; // atomowy zapis do x // Uwaga, ta operacja jest niewspierana x *= 2; // ERROR // Atomowy odczyt x, po którym następuje atomowy zapis do x (dwie operacje) x = x * 2;W przykładzie poniżej, atomic posłużył do blokowania wątków, tak aby funkcje even/odd drukowały naprzemiennie tekst w momencie inkrementacji. Uwaga, nie ma gwarancji, że wartość counter wyświetlana na ekranie będzie zgodna z tym co było sprawdzane w if. Są to dwie atomowe operacje odczytu z pamięci, a wartość counter może się zmienić pomiędzy nimi.
#include <iostream> #include <thread> #include <atomic> using namespace std; std::atomic<int> counter{0}; void odd(size_t n) { for (size_t i = 0; i < n; i++) { if (counter % 2 == 1) { cout << "Odd increment: " << counter << endl; counter++; } else { cout << "Odd check: " << counter << endl; // wartość mogła się zmienić } std::this_thread::sleep_for(std::chrono::milliseconds{20}); } } void even(size_t n) { for (size_t i = 0; i < n; i++) { if (counter % 2 == 0) { cout << "Even increment: " << counter << endl; counter++; } else { cout << "Even check: " << counter << endl; // wartość mogła się zmienić } std::this_thread::sleep_for(std::chrono::milliseconds{40}); } } int main() { constexpr size_t steps{6}; std::thread t1{odd, steps}; std::thread t2{even, steps}; t1.join(); t2.join(); }Wynik:
Odd check: 0 Even increment: 0 Odd increment: 1 Even increment: 2 Odd increment: 3 Odd check: 4 Even increment: 4 Odd increment: 5 Odd check: 6 Even increment: 6 Even check: 7 Even check: 7
#include <iostream> #include <vector> #include <variant> using namespace std; struct Circle { void show() const { cout << "Circle" << endl; } }; struct Rect { void show() const { cout << "Rect" << endl; } }; int main() { using Variant = std::variant<Circle, Rect>; vector<Variant> vec; vec.push_back(Circle{}); vec.push_back(Rect{}); for (const auto& v : vec) { std::visit([](const auto& obj){ obj.show(); }, v); } }Wynik:
Circle Rect
#include <iostream> #include <type_traits> using namespace std; template<typename T> std::enable_if_t<std::is_arithmetic_v<T>, std::string> as_string1(T x) { return std::to_string(x) + " [is_arithmetic_v]"; } template<typename T> std::enable_if_t<std::is_same_v<T, std::string>, std::string> as_string1(T x) { return x + " [is_same_v]"; } template<typename T> std::enable_if_t<!std::is_same_v<T, std::string> && !std::is_arithmetic_v<T>, std::string> as_string1(T x) { return std::string(x) + " [!is_same_v && !is_arithmetic_v]"; } int main() { cout << as_string1(11) << endl; cout << as_string1(std::string("12")) << endl; cout << as_string1("13") << endl; }Wynik:
11 [is_arithmetic_v] 12 [is_same_v] 13 [!is_same_v && !is_arithmetic_v]Inna wersja, gdzie enable_if pojawia się jako parametr szablonowy. Domyślne argumenty szablonowe, nie są częścią sygnatury funkcji szablonowej, trzeba więc do enable_if przekazać jeszcze dummy typ (int), nie wiem czemu trzeba przypisać do tego 0. Dziwny hack.
#include <iostream> #include <type_traits> using namespace std; template<typename T, std::enable_if_t<std::is_arithmetic_v<T>, int> = 0> std::string as_string2(T x) { return std::to_string(x) + " [is_arithmetic_v]"; } template<typename T, std::enable_if_t<std::is_same_v<T, std::string>, int> = 0> std::string as_string2(T x) { return x + " [is_same_v]"; } template<typename T, std::enable_if_t<!std::is_same_v<T, std::string> && !std::is_arithmetic_v<T>, int> = 0> std::string as_string2(T x) { return std::string(x) + " [!is_same_v && !is_arithmetic_v]"; } int main() { cout << as_string2(21) << endl; cout << as_string2(std::string("22")) << endl; cout << as_string2("23") << endl; }Wynik:
21 [is_arithmetic_v] 22 [is_same_v] 23 [!is_same_v && !is_arithmetic_v]Są jeszcze inne formy zapisu enable_if np. jako parametr funkcji, ale w tej chwili nie jest to istotne. W C++17 pojawił się ciekawy mechanizm if constexpr, który pozwala radzić sobie z dużą liczbą takich specjalizacji, a kod wygląda znacznie bardziej czytelnie.
#include <iostream> #include <type_traits> using namespace std; template<typename T> std::string as_string3(T x) { if constexpr(std::is_arithmetic_v<T>) { return std::to_string(x) + " [is_arithmetic_v]"; } else if constexpr(std::is_same_v<T, std::string>) { return x + " [is_same_v]"; } else { return std::string(x) + " [!is_same_v && !is_arithmetic_v]"; } } int main() { cout << as_string3(31) << endl; cout << as_string3(std::string("32")) << endl; cout << as_string3("33") << endl; }Wynik:
31 [is_arithmetic_v] 32 [is_same_v] 33 [!is_same_v && !is_arithmetic_v]