【BSC】使用Python实现PancakeSwap自动交易(入门篇)

news2025/7/22 19:08:59

需求

最近我们需要在BSC上实现代币的自动化交易,比如自动把BNB兑换成USDT,自动把USDT兑换成CAKE等其它代币,同时也要监视价格,在价格合适的时候再兑换代币。而PancakeSwap正是BSC上最大的去中心化交易平台,我们已经学会了手动在PancakeSwap上进行交易,那么如何使用Python对这个操作进行自动化呢?

快速学习法

本文从新手的角度,讲解如何在面对一个从来没接触过的新事物时,快速上手做出东西来。
我们在学习一些新知识,新编程语言,新框架的时候,往往会陷入一个误区,就是总想一来就要把东西从头到尾的啃透,在网上找了一大堆资料、书籍、视频,然后正襟危坐的从第一页开始学起,过不了多久,就会越来越枯燥,越来越疲惫,从而半途而费。

多年来我总结出了一种快速学习法,就是先借助搜索引擎看个大概,对目标事物有个基本了解,然后就直接动手开始操练,刚开始肯定是写的磕磕绊绊,但是不要紧,边写边查边改,慢慢摸索,很快就能写出个勉强能用的东西,接下来再慢慢改进,不断优化,最终改成一份能放入产品的代码,此时基本用法已经学到个七七八八了,再越到类似需求则可以融会贯通,快速做出东西。

调用合约

要实现在PancakeSwap上进行自动交易的需求,首先我们了解到,PancakeSwap的底层是一套智能合约。那么第一步我们的目标就是学会使用Python调用智能合约。

通过一番搜索我们找到了一个名为【web3.py】的库,正是做这个事情的。

初略阅读一下【web3.py】的文档,我们直接看调用合约的部分:
https://web3py.readthedocs.io/en/v5/contracts.html#contractcaller
文档中有大量的示例可以参考:
https://web3py.readthedocs.io/en/v5/examples.html

接下来马上动手操练,写一个调用合约的代码,比如调用BUSD的合约,查询我们的BUSD余额。

我们在BSC浏览器上找到BUSD的合约地址:
https://bscscan.com/address/0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56#readContract

在这里插入图片描述

在下方的【Contract】选项卡,我们可以看到该合约的方法,其中【Read Contract】是只读方法,用于查询一些数据,不需要签名即可调用,【Write Contract】是写入方法,需要签名授权才可以调用,我们可以直接在这边页面手动测试,比如上图中,在【balanceOf】方法中输入我们的钱包地址,点击【Query】按钮就可以查出我们的余额,由于USDT有18位小数精度,所以这个数值需要除以 10^18,就可以得到人类可读的余额约为 35.026 BUSD。其实这是一个标准的ERC20代币合约,在BSC上也称为【BEP20 Token】 标准,有着统一的ABI接口,但先不用了解那么多,我们直接上手,使用Python的【web3.py】库,调用这个合约的【balanceOf】方法:

import web3
from decimal import Decimal
import json

client = web3.Web3(web3.HTTPProvider("https://bsc-dataseed1.binance.org"))

address_busd = "0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56"

abi_busd = json.loads(r'[{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"constant":true,"inputs":[],"name":"_decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"_name","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"_symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burn","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mint","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"renounceOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}]')


def main():
    contract = client.eth.contract(address = address_busd, abi = abi_busd)
    balance = contract.caller.balanceOf("0xeaC7d998684F50b7A492EA68F27633a117Be201d")
    balance = Decimal(balance) / (10 ** 18)
    print(balance)


if __name__ == '__main__':
    main()

执行结果:
在这里插入图片描述
果然成功调用合约拿到了余额数字

合约ABI

代码其中有个参数是abi_busd,即BUSD这个合约的ABI,这个ABI从哪里来呢,依然是在BSC浏览器里面查询合约地址就可以找到:
https://bscscan.com/address/0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56#code

在这里插入图片描述
在【Contract】的【Code】里可以找到它的ABI,是一个JSON,复制出来即可。

ABI我们可以理解为对该合约所有公开方法的描述,它声明了函数名,函数参数个数、类型,返回值,这样在调用该合约的时候才能正确的序列化参数以及获取返回值,不难理解为什么要有这么个东西,想想在Windows上的C++开发中,很多第三方闭源库都是提供一个DLL文件和一个 .h头文件和一个 .lib 导入库,.h里的函数定义就如同这些JSON ABI,描述每个函数的函数名和参数,我们才能正确调用,至于C# 的DLL为什么可以直接调用而不需要接口描述文件,那是因为它的接口描述信息已经写到了DLL中,可以直接从DLL文件读取。

那么这个合约的ABI文件,除了从BSC浏览器中手动复制,有没有办法从网络上获取呢?当然是有的,【bscscan】提供了很多API其中就包括获取合约ABI的API,文档在此:
https://docs.bscscan.com/api-endpoints/contracts

import web3
from web3.middleware import geth_poa_middleware
from decimal import Decimal
import requests

client = web3.Web3(web3.HTTPProvider("https://bsc-dataseed1.binance.org"))

# 连接公共节点需要注入此中间件
client.middleware_onion.inject(geth_poa_middleware, layer=0)

# 我们的钱包地址
address_wallet = "0xeaC7d998684F50b7A492EA68F27633a117Be201d"
private_key = "私钥填在这里"

# BUSD合约地址
address_busd = "0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56"

# pancakeswap合约地址
address_pancakeswap = "0x10ED43C718714eb63d5aA57B78B54704E256024E"

# 获取合约ABI
def fetch_abi(address):
    url = "https://api.bscscan.com/api"
    params = {
        "module": "contract",
        "action": "getabi",
        "address": address,
        "apikey": "6HQZV977GIY8FNT36XN1JJSE12IP2IYVTQ",
    }
    resp = requests.get(url, params = params).json()
    return resp["result"]

# 获取账户ERC20代币余额
def erc20_balance(address_erc20: str, wallet: str) -> Decimal:
    abi_busd = fetch_abi(address_erc20)
    contract = client.eth.contract(address=address_erc20, abi=abi_busd)
    # 先获取该代币精度
    decimals = contract.functions.decimals().call()
    # 获取代币余额
    balance = contract.functions.balanceOf(wallet).call()
    balance = Decimal(balance) / (10 ** decimals)
    return balance

def main():
    balance = erc20_balance(address_busd, address_wallet)
    print(balance)

if __name__ == '__main__':
    main()

于是我们写了一个Python函数用于从网上获取ABI,这样在调用不同合约的时候,就不用一一手动复制ABI了。

注意上面的 apikey 是 bscscan.com 的 apikey ,我们可以在这里注册账号免费申请:https://bscscan.com/apis

免费版的 apikey 一天可以调用10万次 bscscan API,足够使用了。

不过这种从网上获取ABI的方式,在项目实践中最好获取一次然后缓存到本地,可以存到数据库也可以存到文本文件,总之每调用一次合约函数,就要发送HTTP请求获取一次ABI,是不太明智的选择,当然我们现在是学习阶段,这样简单写一写也无妨。

授权

接下来,我们需要调用 PancakeSwap 合约,实现代币的兑换,以BUSD兑换CAKE为例,最简单快速的方法,就是直接去 PancakeSwap 网页上手动发起一笔交易,待交易成功后,到BSC浏览器里查看链上的交易记录,看它调用了哪个合约的哪个方法,传递了什么参数,然后使用Python写代码,照葫芦画瓢即可。
在这里插入图片描述
首先,在 PancakeSwap 第一次交易某种代币时,需要授权,这个授权实际上是调用 BUSD 合约的【approve】方法,将我们账户的BUSD授权给 PancakeSwap 的合约进行支配,这样在接下来的兑换交易中,PancakeSwap 的合约才有权从我们账户中提取我们的BUSD代币,然后缓存CAKE代币转给我们。这个授权该如何用Python去实现呢?最简单的方法是直接提交交易,然后到BSC浏览器查询这笔交易:
https://bscscan.com/tx/0x6bdb716c91b4446dc9f66305578569241eb6b3ee058d943730a9ff3645f7994f#eventlog
在这里插入图片描述
在 Logs 这里我们可以看到这笔授权交易调用了
0xe9e7cea3dedca5984780bafc599bd69add087d56 合约(BUSD合约)的 Approval 方法
在这里插入图片描述
在【Overview】中我们可以看到传递的两个参数值是什么

再到BSC浏览器中查看BUSD的合约方法:
在这里插入图片描述
确实有【approve】这个方法,我们也可以直接在这里输入一样的参数进行手动测试,以验证结果。网上搜索资料,我们可以了解到这两个参数的意思,【spender】就是授权给谁,这里是授权给PancakeSwap的合约地址,【amount】是授权金额,图片里的这个值就是uint256的最大值,最终结果就等同于【无限制】。

接下来我们用Python代码实现这个授权操作:

import web3
from web3.middleware import geth_poa_middleware
from decimal import Decimal
import requests

client = web3.Web3(web3.HTTPProvider("https://bsc-dataseed1.binance.org"))

# 连接公共节点需要注入此中间件
client.middleware_onion.inject(geth_poa_middleware, layer=0)

# 我们的钱包地址
address_wallet = "0xeaC7d998684F50b7A492EA68F27633a117Be201d"
private_key = "私钥填在这里"

# BUSD合约地址
address_busd = "0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56"

# pancakeswap合约地址
address_pancakeswap = "0x10ED43C718714eb63d5aA57B78B54704E256024E"

# 获取合约ABI
def fetch_abi(address):
    url = "https://api.bscscan.com/api"
    params = {
        "module": "contract",
        "action": "getabi",
        "address": address,
        "apikey": "6HQZV977GIY8FNT36XN1JJSE12IP2IYVTQ",
    }
    resp = requests.get(url, params = params).json()
    return resp["result"]

# 授权pancakeswap合约使用我们账户的BUSD代币
def approve_busd_to_pancakeswap(wallet: str):
    abi_busd = fetch_abi(address_busd)
    contract = client.eth.contract(address=address_busd, abi=abi_busd)
    txn = contract.functions.approve(address_pancakeswap, 2 ** 256 - 1).build_transaction({
        "chainId": client.eth.chain_id,
        "from": wallet,
        "nonce": client.eth.get_transaction_count(wallet),
        "gasPrice": client.eth.gas_price
    })
    signed_txn = client.eth.account.sign_transaction(txn, private_key)
    txn_hash = client.eth.send_raw_transaction(signed_txn.rawTransaction)
    txn_hash = client.toHex(txn_hash)
    return txn_hash

def main():
    txn_hash = approve_busd_to_pancakeswap(address_wallet)
    print(txn_hash)

if __name__ == '__main__':
    main()

查询价格

授权完成后,在进行兑换交易之前,我们需要先查询兑换价格,这样才能确定多少代币可以兑换多少另一种代币,我们以BUSD购买CAKE为例,先查询一个BUSD可以买多少个CAKE。

我们先在BSC浏览器中找到 PancakeSwap 的合约地址:
https://bscscan.com/address/0x10ed43c718714eb63d5aa57b78b54704e256024e#readContract
在这里插入图片描述
同理,我们在下方的【Contract】【Read Contract】中可以测试该合约的所有可读方法,其中【getAmountsOut】方法就是用于查询多少A代币可以兑换多少B代币的函数,我们可以直接在这里手动测试,其中【amountIn】参数就是输入多少A代币,【path】参数就是兑换路径,这是一个数组,这里我们填入BUSD的合约地址和CAKE的合约地址即可,表示直接从BUSD兑换成CAKE,因为这两个代币之间有一个很大的流动性池子,可以直接兑换。有的时候,要兑换的两种代币之间没有池子,则需要将A先换成B再换成C,这个时候【path】就有三个元素,分别是A/B/C代币的合约地址。
在这里插入图片描述
比如要把HIGH兑换成CAKE,由于HIGH和CAKE之间没有池子,所以需要先讲HIGH换成BUSD再换成CAKE,那么【path】就需要三个元素,分别是HIGH/BUSD/CAKE的合约地址。

弄清楚大致原理后,我们就可以着手写Python代码如下:

import web3
from web3.middleware import geth_poa_middleware
from decimal import Decimal
import requests

client = web3.Web3(web3.HTTPProvider("https://bsc-dataseed1.binance.org"))

# 连接公共节点需要注入此中间件
client.middleware_onion.inject(geth_poa_middleware, layer=0)

# 我们的钱包地址
address_wallet = "0xeaC7d998684F50b7A492EA68F27633a117Be201d"

# BUSD合约地址
address_busd = "0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56"

# CAKE合约地址
address_cake = "0x0E09FaBB73Bd3Ade0a17ECC321fD13a19e81cE82"

# pancakeswap合约地址
address_pancakeswap = "0x10ED43C718714eb63d5aA57B78B54704E256024E"

# 获取合约ABI
def fetch_abi(address):
    url = "https://api.bscscan.com/api"
    params = {
        "module": "contract",
        "action": "getabi",
        "address": address,
        "apikey": "6HQZV977GIY8FNT36XN1JJSE12IP2IYVTQ",
    }
    resp = requests.get(url, params = params).json()
    return resp["result"]

# 查询CAKE与BUSD兑换价格
def query_cake_price() -> Decimal:
    abi_pancakeswap = fetch_abi(address_pancakeswap)
    contract = client.eth.contract(address=address_pancakeswap, abi=abi_pancakeswap)
    price = contract.functions.getAmountsOut(1 * 10 ** 18, [address_busd, address_cake]).call()
    return Decimal(price[1]) / (10 ** 18)

def main():
    price = query_cake_price()
    print(price)

if __name__ == '__main__':
    main()

执行结果:
在这里插入图片描述
可以看到,执行结果为,1个BUSD可以换约0.2535个CAKE
需要注意的是,函数中的 10 ** 18,因为我们知道 BUSD 和 CAKE 的精度都是18位小数,所以我们在这里直接写死了,在实际项目中需要根据你的情况更改。

兑换交易

接下来最后一步就是进行兑换交易了,我们可以先手动兑换一笔,然后查看交易记录:
https://bscscan.com/tx/0x71f5d27d08803ca834b685c86b7f8a2b72039b468fc6600256a18e8ba0c7a173
在这里插入图片描述
我们可以看到它调用了 PancakeSwap 合约的 【swapExactTokensForTokens】方法,【Decode Input Data】后可以看到传递的参数是什么:
在这里插入图片描述
有同学就要问了,你怎么知道 PancakeSwap 合约的这些方法和参数是什么含义呢?包括上面的【getAmountsOut】方法,答案就在PancakeSwap的文档中,解释得很清楚了:
https://docs.pancakeswap.finance/code/smart-contracts/pancakeswap-exchange/v2/router-v2

接下来我们用 Python 代码实现兑换操作:

import web3
from web3.middleware import geth_poa_middleware
from decimal import Decimal
import requests
from datetime import datetime, timedelta

client = web3.Web3(web3.HTTPProvider("https://bsc-dataseed1.binance.org"))

# 连接公共节点需要注入此中间件
client.middleware_onion.inject(geth_poa_middleware, layer=0)

# 我们的钱包地址
address_wallet = "0xeaC7d998684F50b7A492EA68F27633a117Be201d"
private_key = "私钥填在这里"

# BUSD合约地址
address_busd = "0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56"

# CAKE合约地址
address_cake = "0x0E09FaBB73Bd3Ade0a17ECC321fD13a19e81cE82"

# pancakeswap合约地址
address_pancakeswap = "0x10ED43C718714eb63d5aA57B78B54704E256024E"

# 获取合约ABI
def fetch_abi(address):
    url = "https://api.bscscan.com/api"
    params = {
        "module": "contract",
        "action": "getabi",
        "address": address,
        "apikey": "6HQZV977GIY8FNT36XN1JJSE12IP2IYVTQ",
    }
    resp = requests.get(url, params = params).json()
    return resp["result"]

# 将BUSD兑换为CAKE
def swap_busd_to_cake(wallet: str, amount_busd: Decimal):
    abi_pancakeswap = fetch_abi(address_pancakeswap)
    contract = client.eth.contract(address=address_pancakeswap, abi=abi_pancakeswap)
    price_cake = contract.functions.getAmountsOut(1 * 10 ** 18, [address_busd, address_cake]).call()
    price_cake = Decimal(price_cake[1]) / (10 ** 18)
    # 滑点0.5% 交易手续费 0.25% ,则最小换得的cake数量为理论换得的cake数量 乘 99.25 %
    amount_cake_min = int(price_cake * amount_busd * Decimal("0.9925") * 10 ** 18)
    amount_busd = int(amount_busd * 10 ** 18)
    # deadline为交易必须在此时间前确认,否则交易失败,我们在pancakeswap网页上手动操作的时候默认是20分钟,所以照着它来
    deadline = datetime.now() + timedelta(minutes = 20)
    txn = contract.functions.swapExactTokensForTokens(amount_busd, amount_cake_min, [address_busd, address_cake], wallet, int(deadline.timestamp())).build_transaction({
        "chainId": client.eth.chain_id,
        "from": wallet,
        "nonce": client.eth.get_transaction_count(wallet),
        "gasPrice": client.eth.gas_price
    })
    signed_txn = client.eth.account.sign_transaction(txn, private_key)
    txn_hash = client.eth.send_raw_transaction(signed_txn.rawTransaction)
    txn_hash = client.toHex(txn_hash)
    return txn_hash

def main():
    txn_hash = swap_busd_to_cake(address_wallet, Decimal("1.0"))
    print(txn_hash)

if __name__ == '__main__':
    main()

执行以后,交易成功,perfect !
https://bscscan.com/tx/0xbb7de1e37f332bd8114ba8d58cf3a13226d76194dc8cc08f3e7dac9ba00df4a0
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/7682.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2022行情变了,请各位做好一年内随时失业的准备

前两天跟一个HR朋友聊天,她表示刚在boss上发布了一个普通测试岗位,不到一小时竟然收到了几百份简历。而且简历质量极高,这是往年不敢想象的。岗位少,竞争激烈,这是今年软件测试就业的真实写照,也是所有岗位…

【附源码】计算机毕业设计JAVA畜牧场信息管理系统

【附源码】计算机毕业设计JAVA畜牧场信息管理系统 目运行 环境项配置: Jdk1.8 Tomcat8.5 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: JAVA …

个人如何调用股票程序交易接口?

关于股票程序交易接口的调用一般只有量化交易投资者才能涉及的到,那么做常见也最实用的方法就是使用外接端口,意思就是可以买一个接口就可以接入交易软件了,不过要具有编程基础才能实现,因为现有的策略和设置的函数都是无法满足投…

OSI七层模型

介绍 七层模型,亦称OSI(Open System Interconnection)。参考模型是国际标准化组织(ISO)制定的一个用于计算机或通信系统间互联的标准体系,一般称为OSI参考模型或七层模型。 分层 应用层 提供高级api …

HDFS 基本 shell 操作

HDFS 基本 shell 操作1.1 创建目录1.2 上传指令1.3 创建空文件1.4 向分布式文件系统中的文件里追加内容1.5 查看指令1.6 下载指令1.7 合并下载1.8 移动hdfs中的文件1.9 复制hdfs中的文件到hdfs的另一个目录1.10 删除命令1.11 查看磁盘利用率和文件大小1.12 修改权限1.13 修改文…

子进程信号继承;kill+raise+alarm+pause+信号发生接收和处理+信号屏蔽

子进程对父进程信号继承情况 fork创建子进程,但子进程没有exec 在fork子进程之前: 如果父进程调用signal设置了某个信号的处理方式的话,那么fork出的子进程会继承父进程对该信号设置的处理 强调:只有在fork之前,父进程所设置的信号处理方式&…

餐厅扫码点餐怎么弄_分享扫码点餐小程序开发制作方法

目前市场上有很多扫码点餐的小程序系统,制作方法有三种: 1、使用微信商家推出的扫码点餐小程序,上传营业执照和食品经营许可证就可以开通使用,然后上传自己的菜品信息就可以了,功能相对比较简单。 2、购买餐饮系统公司…

Redis数据持久化(持久化过程中写操作如何处理)

上一节简单分析了Redis数据持久化方式,点击这里查看。但是要考虑的一个问题就是,在Redis持久化的时候,有新的写入指令时,Redis是如何操作的。 1.RDB方式 1.1.同步方式 即save操作,在Redis执行save操作时,…

systemVerilog的变量类型转换

1 Type Casting 1.1 Verilog使用赋值语句进行变量类型转换 阻塞赋值&#xff1a; 非阻塞赋值&#xff1a; < 1.2 systemVerilog增加了变量类型转换符 变量类型转换符可以在任何时刻对表达式进行类型转换而不像Verilog一样只能发生在赋值语句中 logicint a&#xff0c;y&…

开放式运动耳机怎么样,几款合适的骨传导耳机推荐

骨传导作为新时代的产物&#xff0c; 近些年在耳机市场也是兴起了一波热潮&#xff0c;无论是在日常出勤时佩戴&#xff0c;还是在运动的时候佩戴&#xff0c;骨传导耳机相对于传统耳机来说无疑是越来越符合。其骨传导最大的特点无非就是特殊的传声方式以及无需入耳的佩戴&…

每日一个设计模式之【外观模式】

文章目录每日一个设计模式之【外观模式】☁️前言&#x1f389;&#x1f389;&#x1f389;&#x1f33b;外观模式概述&#x1f331;外观模式的实现&#x1f332;总结每日一个设计模式之【外观模式】 ☁️前言&#x1f389;&#x1f389;&#x1f389; 大家好✋&#xff0c;我…

【c++】四种类型转换的用法

这里写目录标题static_cast 无条件转换&#xff0c;静态类型转换const_cast 去掉类型的const或volatile属性dynamic_cast 有条件转换&#xff0c;动态类型转换&#xff0c;运行时检查类型安全&#xff08;转换失败返回NULL&#xff09;reinterpret_cast 仅重新解释类型&#xf…

离散数学(十二):关系的幂运算与关系的性质

1 关系的幂运算 1&#xff09;幂运算的定义 2&#xff09;幂运算的求法 幂运算有两种求法&#xff0c;基于矩阵的方法和基于关系图的方法。我们之前学过关系的表示方法有三种&#xff1a;集合、矩阵、关系图。那么同样&#xff0c;这些方式也可以运用于关系的计算中。 需…

leaflet教程029: 加载KML文件(代码示例)

第029个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+leaflet中加载kml文件,将图形显示在地图上。 直接复制下面的 vue+leaflet源代码,操作2分钟即可运行实现效果 文章目录 示例效果配置方式安装leaflet-plugins本示例引用的kml文件代码示例源代码(共79行)专栏目标…

【容器网络】跨主通信网络实现方法之host-gw实现原理

以上是VXLAN在跨主通信的实现原理&#xff0c;本文讲述的是host-gw的实现原理。 目录 Host-gw 基本原理 flannel的host-gw 数据包传输过程 calico的host-gw calico架构 BGP Peer Node-to-NodeMesh Route Reflector IPIP Host-gw 在容器生态中,提供 Host-gw解决方案…

Seata AT模式TransactionHook会被莫名删除?

前言 兄弟们&#xff0c;刚刚又给seata社区修了一个BUG&#xff0c;有用户提了issue反应TransactionHook在某些情况下不会被调用&#xff1a; 该用户在issue中已经指出了相关问题所在&#xff1a; 下面我们来看一下到底是什么原因导致了上述BUG的产生。 问题定位 根据用户的…

最新JMeter面试题,紧扣面试实际要求,看完拿下20K

JMeter是一款纯java编写负载功能测试和性能测试开源工具软件。相比Loadrunner而言&#xff0c;JMeter小巧轻便且免费&#xff0c;逐渐成为了主流的性能测试工具&#xff0c;是测试人员必须要掌握的工具之一。 下面小编给大家总结了22年最新30道关于JMeter的面试题&#xff0c;…

基于51单片机的温度报警系统

功能&#xff1a; 设计一个温度报警系统&#xff0c;可以设定温度上、下限的值&#xff0c;到达设定值时&#xff0c;蜂鸣器响&#xff1b;按键设定有设置、确定、取消、减少与增加功能&#xff0c;LCD1602实时显示相关温度信息 设定界面&#xff1a; 温度超过设定值&#xf…

美国能源部国家实验室将量子计算用于关键能源研究

​ &#xff08;图片来源&#xff1a;网络&#xff09; 量子计算是一种新兴的、强大而有前途的且能快速解决复杂问题的新力量&#xff0c;美国能源部国家实验室NETL的专家正准备将量子计算投入到关键能源的研究课题上&#xff0c;以实现环境可持续和能源应用的无限未来。 量子…

【MySQL | 运维篇】05、MySQL 分库分表之 使用 MyCat 分片

目录 一、垂直拆分 1.1 场景 1.2 准备 1.3 配置 1). schema.xml 2). server.xml 1.4 测试 1). 上传测试SQL脚本到服务器的 /root/sql 目录 2). 执行指令导入测试数据 3). 查询用户的收件人及收件人地址信息(包含省、市、区)。 4). 查询每一笔订单及订单的收件地址信息…