如何将jenkins部署到远程服务器

部署步骤

安装java环境对外开放端口安装tomcat服务器部署jenkins.war
说明:本次部署服务器为 centos 6,本小节是介绍jenkins的部署

1.安装java

在服务器安装java

yum -y install java # 安装java

yum -y remove java # 卸载java

有的服务器自带java,但是版本可能是1.7,需要先卸载
先卸载自带的Java,然后再重新安装Java (不卸载的话,提示Java1.7.0就是*新版)
验证
java –version

iptables -A INPUT -p tcp -m state –state NEW -m tcp –dport 8080 -j ACCEPT

ssh -i /root/.ssh/ido_sch_pro root@78.141.208.80 -p 8080

安装成功提示和验证

如何将jenkins部署到远程服务器
2.对外开放端口

服务器开放端口(自己的)

写入
/sbin/iptables -I INPUT -p tcp –dport 8080 -j ACCEPT

保存
/etc/init.d/iptables save

重启防火墙
service iptables restart
也可以通过控制台开通

也可以找网管开通(牵扯到*,可能你没有权限)

3.安装tomcat服务器(8080)

下载tomcat

如何将jenkins部署到远程服务器
移动文件(根据个人喜好)

可以使用scp命令移动

scp 本地资源 root@ip:/home/root/xxx

也可以借助工具

如何将jenkins部署到远程服务器
安装

1. 解压到你想安装的位置(解压完,压缩包可以删除了)
tar -zxvf apache-tomcat-8.5.35.tar.gz -C /usr/local

2. 进入bin目录
cd /usr/local/apache-tomcat-8.5.35/bin

3. 启动(此处不配置端口,默认是8080)
./startup.sh

4. 关闭
./shutdown.sh

验证

在 浏览器地址栏输入 你的服务器ip:8080 能看到如下图,就说明已安装好 tomcat了

如何将jenkins部署到远程服务器
4.将jenkins.war部署

将jenlkins.war部署到tomcat中的webapps

如何将jenkins部署到远程服务器
验证

在 浏览器地址栏输入 服务器ip:8080/jenkins *次是这个页面(和本地部署时一致的)

如何将jenkins部署到远程服务器
在上个和图中,找到密码文件,查找密码

如何将jenkins部署到远程服务器
安装插件之后,登录成功

如何将jenkins部署到远程服务器

iOS应用内付费(In-App Purchase,IAP,内购)实现要点总结

在iOS实现内购,需要接入StoreKit framework以完成玩家支付。为了保证支付的安全性,在玩家支付后,游戏并不是立即下发虚拟物品,而是拿着StoreKit从App Store收到的receipt(票据,可以理解为买东西付钱后开的发票),通过本地或者服务器向App Store发起验证,确认交易的合法性后,再发放游戏商品或者解锁游戏特性。

接入StoreKit之前的准备工作
在App Store Connect配置内购物品的Product ID
共有4种内购类型可供选择,其中常用的有两种:

Consumables ,可消耗的,也就是玩家在游戏里可以装备或者花掉的,比如金币,装备,皮肤等。它是可以被玩家重复购买的,且只针对当前购买的设备有效。换句话说我在A设备上买的金币是不能再B设备上花的。
Non-consumables,不可消耗的,也就是玩家只要买一次就能永久有效的,比如开启关卡,移除广告等。这种购买是在玩家所有设备上都有效的。总不能我再A设备上移除广告,换了B设备,就又要再次移除广告。
注意:如果是按时间收费的内购,应该设置为Non-Renewing Subscription(不可更新的订阅),否则审核会被拒。
在App Store Connect申请测试账号
在测试的iOS设备上退出普通账号,然后启动游戏,在游戏提交支付时StoreKit会提示你登录,这时用测试账号登录并支付,交易完成,但不会真的扣款。这里要注意:测试账号不能直接在设置里登录,否则会失效。
沙盒测试时验证receipt用的url和生产环境用的url是不一样的。它们分别是
沙盒环境,“https://sandbox.itunes.apple.com/verifyReceipt”
生产环境,“https://buy.itunes.apple.com/verifyReceipt”
所以在实际验证receipt的时候,我们一般先用生产url验证票据,如果收到21007状态码,则表明这是个沙盒票据,那么接着就切换到沙盒url验证,从而避免手动在这两种环境之间切换。
在正确配置好Product ID和测试账号后,通常需要等待一段时间,*长24小时,否则可能遇到沙盒测试购买失败的情况。这是因为App Store准备沙盒测试环境需要一段时间。

接入StoreKit
获取Product信息
有了Product ID,我们就可以建立一个Product请求(SKProductsRequest,以一组Product ID初始化,指定一个实现协议 SKProductsRequestDelegate的代理以处理请求结果SKProductsResponse),向App Store获取合法的Product的本地化信息(保存在SKProduct中),填充到制作好的Store界面上,同时App Store还会返回请求里不合法的Product ID列表。不可识别的原因通常是ID拼写错误、标记为不可销售、Connect的信息还未同步到其他App Store服务器等。下面是上述的简单实现样例:

// 你定义的异步验证Product ID和获取Product信息的方法
– (void)validateProductIdentifiers:(NSArray *)productIdentifiers
{
SKProductsRequest *productsRequest = [[SKProductsRequest alloc]
initWithProductIdentifiers:[NSSet setWithArray:productIdentifiers]];

// 保存request引用,避免被游戏回收
self.request = productsRequest;
productsRequest.delegate = self; // 当前所在的类实现了SKProductsRequestDelegate协议
[productsRequest start];
}

// SKProductsRequestDelegate 协议接口的实现
– (void)productsRequest:(SKProductsRequest *)request
didReceiveResponse:(SKProductsResponse *)response
{
// 包含product的本地化信息,保存product列表,后面请求交易时需要用到
self.products = response.products;

for (NSString *invalidIdentifier in response.invalidProductIdentifiers) {
// 处理不合法的Product ID,可以简单打印或者弹个Alert
}

[self displayStoreUI]; // 你定义的显示商店界面的方法
}

向App Store请求支付
首先要查询玩家是否允许支付,因为iOS可以在设置里禁止IAP支付。如下:
if ([SKPaymentQueue canMakePayments]) {
// 请求支付
} else {
NSLog(@”失败,用户禁止应用内付费购买.”);
}

创建一个支付请求SKPayment,并设置想要购买的数量quantity。然后追加请求到支付队列SKPaymentQueue中, 通过StoreKit将支付请求发送到App Store中。如果这个请求被添加多次,那么它也会提交到App Store多次,每次都会要求玩家付费并让游戏下发内购物品。代码如下:
SKProduct *product = <# 之前获得的产品信息 #>;
SKMutablePayment *payment = [SKMutablePayment paymentWithProduct:product];
payment.quantity = 3;
[[SKPaymentQueue defaultQueue] addPayment:payment];

处理交易对象Transaction
每次向支付队列添加支付请求,App Store都会生成对应的交易对象Transaction并添加到交易队列里。这是个持久化的对象,即使玩家退出或者重启游戏,下一次都能继续交易。App Store通过StoreKit来同步交易对象,游戏本身要实现自己的交易队列观察者对象(SKPaymentTransactionObserver)来监听交易对象状态的变化并在处理完交易后把交易对象从交易队列中移除。

为了立即响应交易对象的变化,游戏在刚启动的时候就要注册观察者对象。
– (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
/* … */

[[SKPaymentQueue defaultQueue] addTransactionObserver:observer];
}

– (void)applicationWillTerminate:(UIApplication *)application
{
/* … */

[[SKPaymentQueue defaultQueue] removeTransactionObserver:observer];
}

 

在自己的观察者对象类里实现接口paymentQueue:updatedTransactions:。每当交易状态变化时,StoreKit通过这个方法通知游戏执行对应的动作。示例如下:
– (void)paymentQueue:(SKPaymentQueue *)queue
updatedTransactions:(NSArray *)transactions
{
for (SKPaymentTransaction *transaction in transactions) {
switch (transaction.transactionState) {
case SKPaymentTransactionStatePurchasing:
// 你定义的响应正在购买中的方法,等待再次调用
[self showTransactionAsInProgress:transaction deferred:NO];
break;
case SKPaymentTransactionStateDeferred:
// 你定义的响应玩家取消购买的方法,等待再次调用
[self showTransactionAsInProgress:transaction deferred:YES];
break;
case SKPaymentTransactionStateFailed:
// 你定义的响应购买失败的方法,获取transaction的error属性,显示购买失败原因
[self failedTransaction:transaction];
break;
case SKPaymentTransactionStatePurchased:
// 你定义的相关购买成功的方法,通常是下发内购物品或者解锁特性,
// 或者为了进一步保证交易安全性,获取transaction的receipt属性,向服务器验证票据,通过后在下发物品
[self completeTransaction:transaction];
break;
case SKPaymentTransactionStateRestored:
// 你定义的还原之前购买的功能的方法
[self restoreTransaction:transaction];
break;
default:
// For debugging
NSLog(@”Unexpected transaction state %@”, @(transaction.transactionState));
break;
}
}
}

在处理完成功或者失败的交易对象后,调用finishTransaction:,把交易对象从交易队列移除。移除前确保你已经下发商品或者验证票据。在*少数的情况下,这个方法调用会失败,从而再次执行购买,所以你可以记录交易,从而避免重复购买。
验证receipt
这步主要是为了防破解。要注意两点:

发送的票据要持久化,如果游戏崩溃、网络异常、强制关闭后仍然可以恢复重试。
服务器则要记录发送过来的票据是否已经在验证中,或者验证过,避免多发物品和作弊。
代码如下:
/* 从app bundle中加载receipt. */
NSURL *receiptURL = [[NSBundle mainBundle] appStoreReceiptURL];
NSData *receipt = [NSData dataWithContentsOfURL:receiptURL];

if (!receipt) {
NSLog(@”no receipt”);
/* 没有本地 receipt — 处理异常. */
} else {
/* 获取编码后的 receipt */
NSString *encodedReceipt = [receipt base64EncodedStringWithOptions:0];
}

/* … 发送 receipt 数据给你的服务器,
然后服务器建立一个JSON对象,把receipt数据放到receipt-data属性里,
建立一个HTTP POST请求,将JSON对象放入Payload,发送给App Store验证
.

云计算应用的五个特性和四种部署方式

云计算的五个关键特性,用了“SALES”概括,包含了未来的商业模式,服务模式的内涵。如果满足这几个方面,我们就可以说他叫做“云”:

*个是按需自助服务(On Demand Self-Service),前面讲的技术跟业务之间有一个矛盾,如果业务部门可以自助做一些工作,IT压力会减少很多。

第二个就是泛网的访问(Broad Network Access) ,无时无刻可以通过互联网各种方式去访问这种服务。

第三个是资源池(Resource PooLing) ,这个资源是非常广泛的,如果大家通过泛网的访问可以去访问各种资源 ,不光是方便了我们服务的对象,也方便了我们作为云计算支撑服务的自己。

第四个就是快速弹性的扩展(Rapid Elasticity) ,前面讲到我们有很多厂商的支持,在当前的技术条件下,越来越存在这方面的困难了。

第五个就是可计量的服务(Measured Service) ,将来我们可以把我们的服务按照一种商业模式进行划分,这里面对于我们本身做 IT来讲,他是一个价值的体现,我们可以计量到我们自己的IT真正的价值。

云计算的四种部署方式:私有云、社区云、公有云和混合云。“三”种服务方式,指Iaas,Paas,Saas 。*终的形态,将来云的发展会出现这种倒三角,*终的洗牌以后 ,*多的集中在SAAS这一层,但是目前中国处于发展阶段,现在的格局是正三角,相对来说还不是我们*终的方式。
在这种情况下,我们要把资源进行抽象化,平台要按各种业务的需求进行功能化,*终实现软件的服务化。 这样一个格局势必对我们的管理产生很大的变化,将来公司的形态会有很大的变化,将来一些以个体人员的服务方式。

企业构建迁移清单之前,需要考虑哪些注意事项

1.安全性

在数据隐私正成为一个良好数据管理实践的世界中,了解哪些数据是可共享的,哪些数据是不可共享的,这一点很重要。个人用户需要确保其PII(个人身份信息)数据不会暴露给错误的各方是至关重要的。因此,重要的是要全面检查整个管道和数据库功能,以确保运动和静止数据的安全。了解数据如何分阶段,哪些系统可以访问它,以及保留多长时间对于充分了解信息的暴露程度至关重要。

此外,与传统的本地解决方案一样,应该考虑应用程序如何保护对象和数据。例如,是否存在基于角色的访问控制(RBAC)以及是否能够以适当的粒度(行或列级别)保护数据是重要的事项。解除数据标识和屏蔽数据是否是进入云平台的先决条件?并且授权用户管理是企业操作的关键因素吗?

*后,必须知道资产清单中的哪些数据对象需要进行特殊处理才能达到监管或合同目的。在开始迁移和规划过程时,确保平台和应用程序能够支持企业这些需求至关重要。

2.性能

迁移到云平台时,让数据可用且尽可能保持*新状态是至关重要的。数据分析可以提供业务优势,并且依赖于数据。通常,本地解决方案经过精心人工制作和专门设计,以满足业务的用户体验要求和服务等级协议(SLA)。在迁移到云平台时,无论企业使用何种方法,在特定生产工作负载下完全审查和测试管道和数据库的性能至关重要。这是理解性能瓶颈会发生什么,在哪里发生,以及如何解决它们的唯一方法。

为连续测试和监控建立特定基准和候选工作负载无疑是*佳实践。这可以使用云监控服务和查询来完成,这些查询不断轮询并验证平台是否以*佳方式运行。

企业云存储与迁移概述

3.容量

管理当前和未来的容量是本地解决方案领域的一门科学。它与维护平台消费者体验到的一致的性能水平密切相关。迁移到云平台的主要方法之一就是随着工作负载和容量需求的变化,实现弹性和自动扩展带来的优势。

在考虑未来的云计算架构时,至关重要的是,响应峰值需求场景所需的工程设计必须预先构建到平台的功能中。企业需要了解其峰值需求,并确保云平台能够处理它们。确保可以持续测试和监控这些高峰需求情景也很关键。

利用云平台原生的监控和报告服务。让企业DevOps团队了解这些技术,并预先构建这种能力,而不是在迁移之后再进行考虑。

4.资产和库存普查

在执行云端迁移策略之前,企业必须捕获所有数据资产的完整清单,其依赖关系以及上游和下游应用程序支持这些资产的内容。创建和维护此清单是迁移阶段所有计划活动的基础。如果没有这个清单,则无法完全了解将堆栈中的每个组件迁移到云端所带来的影响、风险和成本。

此外,通过此库存和评估练习,企业经常会发现重构和淘汰冗余数据源和服务的机会。这可以帮助企业避免在有限或没有未来价值的项目上浪费资源。企业还可以发现要迁移的新数据源。

5.应用程序迁移

这个迁移指南的重点是数据迁移到云端,但企业可能也需要迁移应用程序。可以选择几种不同的方法来迁移其应用程序。企业自己的特定需求和目标将决定哪种方式*适合自己。

企业是否希望将大多数应用程序迁移到云中,但是避免对它们进行更改。这通常是“提升和转移”方法的一种变体,即在云中托管的虚拟机中运行现有应用程序,而不是定制或替换。它速度更快,破坏性更小,但也无法充分利用云计算提供的所有功能。

iOS 集成apple Pay 接入详细教程

Apple Pay运行环境:iPhone6以上设备,操作系统*低iOS9.0以上,部分信息设置需要iOS9.2以上。目前还不支持企业证书添加。

环境搭建好后可以在模拟器上面运行,xcode7.2.1+iPhone6SP9.2系统下,系统会绑定几种虚拟的银行卡,和几个联系人,方便调试,支付也不会发生真实的付款,真的很方便。

准备工作

在接入Apple Pay之前,首先要申请MerchantID及对应证书。

工程设置

bundleID设置

Capability中启用Apple Pay权限,并选择merchantID。

之后项目会多一个Applepay的配置文件ApplePayYasin.entitlements

需要引用的库

Xcode7.0以上不需要再手动添加需要引用的库了,只需要导入头文件就可以了

 

#import <passkit passkit.h=””>                                 //用户绑定的银行卡信息

#import <passkit pkpaymentauthorizationviewcontroller.h=””>    //Apple pay的展示控件

#import <addressbook addressbook.h=””>                         //用户联系信息相关</addressbook></passkit></passkit>

设备Applepay权限检测

 

if (![PKPaymentAuthorizationViewController class]) {

//PKPaymentAuthorizationViewController需iOS8.0以上支持

NSLog(@”操作系统不支持ApplePay,请升级至9.0以上版本,且iPhone6以上设备才支持”);

return;

}

//检查当前设备是否可以支付

if (![PKPaymentAuthorizationViewController canMakePayments]) {

//支付需iOS9.0以上支持

NSLog(@”设备不支持ApplePay,请升级至9.0以上版本,且iPhone6以上设备才支持”);

return;

}

//检查用户是否可进行某种卡的支付,是否支持Amex、MasterCard、Visa与银联四种卡,根据自己项目的需要进行检测

NSArray *supportedNetworks = @[PKPaymentNetworkAmex, PKPaymentNetworkMasterCard,PKPaymentNetworkVisa,PKPaymentNetworkChinaUnionPay];

if (![PKPaymentAuthorizationViewController canMakePaymentsUsingNetworks:supportedNetworks]) {

NSLog(@”没有绑定支付卡”);

return;

}

创建支付请求PKPaymentRequest

初始化PKPaymentRequest

这里需要注意RMB的币种代码是CNY

 

//设置币种、国家码及merchant标识符等基本信息

PKPaymentRequest *payRequest = [[PKPaymentRequest alloc]init];

payRequest.countryCode = @”CN”;     //国家代码

payRequest.currencyCode = @”CNY”;       //RMB的币种代码

payRequest.merchantIdentifier = @”merchant.ApplePayDemoYasin”;  //申请的merchantID

payRequest.supportedNetworks = supportedNetworks;   //用户可进行支付的银行卡

payRequest.merchantCapabilities = PKMerchantCapability3DS|PKMerchantCapabilityEMV;      //设置支持的交易处理协议,3DS必须支持,EMV为可选,目前国内的话还是使用两者吧

设置发票配送信息和货物配送地址信息,用户设置后可以通过代理回调代理获取信息的更新

 

// payRequest.requiredBillingAddressFields = PKAddressFieldEmail;

//如果需要邮寄账单可以选择进行设置,默认PKAddressFieldNone(不邮寄账单)

//楼主感觉账单邮寄地址可以事先让用户选择是否需要,否则会增加客户的输入麻烦度,体验不好,

payRequest.requiredShippingAddressFields = PKAddressFieldPostalAddress|PKAddressFieldPhone|PKAddressFieldName;

//送货地址信息,这里设置需要地址和联系方式和姓名,如果需要进行设置,默认PKAddressFieldNone(没有送货地址)

送货信息页面展示

设置货物的配送方式,不需要不配置

 

//设置两种配送方式

PKShippingMethod *freeShipping = [PKShippingMethod summaryItemWithLabel:@”包邮” amount:[NSDecimalNumber zero]];

freeShipping.identifier = @”freeshipping”;

freeShipping.detail = @”6-8 天 送达”;

 

PKShippingMethod *expressShipping = [PKShippingMethod summaryItemWithLabel:@”*速送达” amount:[NSDecimalNumber decimalNumberWithString:@”10.00″]];

expressShipping.identifier = @”expressshipping”;

expressShipping.detail = @”2-3 小时 送达”;

 

payRequest.shippingMethods = @[freeShipping, expressShipping];

账单信息的设置

每条账单的设置

账单列表使用PKPaymentSummaryItem添加描述和价格,价格使用NSDecimalNumber。

PKPaymentSummaryItem初始化:

label为商品名字或者是描述,amount为商品价格,折扣为负数,type为该条账单为*终价格还是估算价格(比如出租车价格预估)

 

+ (instancetype)summaryItemWithLabel:(NSString *)label amount:(NSDecimalNumber *)amount;

+ (instancetype)summaryItemWithLabel:(NSString *)label amount:(NSDecimalNumber *)amount type:(PKPaymentSummaryItemType)type NS_AVAILABLE(NA, 9_0);

NSDecimalNumber初始化:

NSDecimalNumber可以使用数字初始化,也可以使用字符串。

使用方法请移步我写的NSDecimalNumber–十进制数

添加账单列表:

 

NSDecimalNumber *subtotalAmount = [NSDecimalNumber decimalNumberWithMantissa:1275 exponent:-2 isNegative:NO];   //12.75

PKPaymentSummaryItem *subtotal = [PKPaymentSummaryItem summaryItemWithLabel:@”商品价格” amount:subtotalAmount];

 

NSDecimalNumber *discountAmount = [NSDecimalNumber decimalNumberWithString:@”-12.74″];      //-12.74

PKPaymentSummaryItem *discount = [PKPaymentSummaryItem summaryItemWithLabel:@”优惠折扣” amount:discountAmount];

 

NSDecimalNumber *methodsAmount = [NSDecimalNumber zero];

PKPaymentSummaryItem *methods = [PKPaymentSummaryItem summaryItemWithLabel:@”包邮” amount:methodsAmount];

 

NSDecimalNumber *totalAmount = [NSDecimalNumber zero];

totalAmount = [totalAmount decimalNumberByAdding:subtotalAmount];

totalAmount = [totalAmount decimalNumberByAdding:discountAmount];

totalAmount = [totalAmount decimalNumberByAdding:methodsAmount];

PKPaymentSummaryItem *total = [PKPaymentSummaryItem summaryItemWithLabel:@”Yasin” amount:totalAmount];  //*后这个是支付给谁。哈哈,快支付给我

 

summaryItems = [NSMutableArray arrayWithArray:@[subtotal, discount, methods, total]];

//summaryItems为账单列表,类型是 NSMutableArray,这里设置成成员变量,在后续的代理回调中可以进行支付金额的调整。

payRequest.paymentSummaryItems = summaryItems;

显示购物信息并进行支付

 

//ApplePay控件

PKPaymentAuthorizationViewController *view = [[PKPaymentAuthorizationViewController alloc]initWithPaymentRequest:payRequest];

view.delegate = self;

[self presentViewController:view animated:YES completion:nil];

PKPaymentAuthorizationViewControllerDelegate代理

这里还有两个类要介绍

PKPayment 支付成功信息

 

PKPaymentToken *payToken = payment.token;

//支付凭据,发给服务端进行验证支付是否真实有效

PKContact *billingContact = payment.billingContact;     //账单信息

PKContact *shippingContact = payment.shippingContact;   //送货信息

PKContact *shippingMethod = payment.shippingMethod;     //送货方式

PKContact 联系人信息

 

NSPersonNameComponents *name = contact.name;                //联系人姓名

CNPostalAddress *postalAddress = contact.postalAddress;     //联系人地址

NSString *emailAddress = contact.emailAddress;              //联系人邮箱

CNPhoneNumber *phoneNumber = contact.phoneNumber;           //联系人手机

NSString *supplementarySubLocality = contact.supplementarySubLocality;  //补充信息,地址详细描述,其他备注等等,iOS9.2及以上才有

代理说明

送货地址回调

 

-(void)paymentAuthorizationViewController:(PKPaymentAuthorizationViewController *)controller

didSelectShippingContact:(PKContact *)contact

completion:(void (^)(PKPaymentAuthorizationStatus, NSArray<pkshippingmethod *> * _Nonnull, NSArray<pkpaymentsummaryitem *> * _Nonnull))completion{

//contact送货地址信息,PKContact类型

//送货信息选择回调,如果需要根据送货地址调整送货方式,比如普通地区包邮+*速配送,偏远地区只有付费普通配送,进行支付金额重新计算,可以实现该代理,返回给系统:shippingMethods配送方式,summaryItems账单列表,如果不支持该送货信息返回想要的PKPaymentAuthorizationStatus

completion(PKPaymentAuthorizationStatusSuccess, shippingMethods, summaryItems);

}</pkpaymentsummaryitem *></pkshippingmethod *>

送货方式回调

 

-(void)paymentAuthorizationViewController:(PKPaymentAuthorizationViewController *)controller

didSelectShippingMethod:(PKShippingMethod *)shippingMethod

completion:(void (^)(PKPaymentAuthorizationStatus, NSArray<pkpaymentsummaryitem *> * _Nonnull))completion{

//配送方式回调,如果需要根据不同的送货方式进行支付金额的调整,比如包邮和付费加速配送,可以实现该代理

PKShippingMethod *oldShippingMethod = [summaryItems objectAtIndex:2];

PKPaymentSummaryItem *total = [summaryItems lastObject];

total.amount = [total.amount decimalNumberBySubtracting:oldShippingMethod.amount];

total.amount = [total.amount decimalNumberByAdding:shippingMethod.amount];

[summaryItems replaceObjectAtIndex:2 withObject:shippingMethod];

[summaryItems replaceObjectAtIndex:3 withObject:total];

 

completion(PKPaymentAuthorizationStatusSuccess, summaryItems);

}</pkpaymentsummaryitem *>

支付卡选择回调

 

-(void)paymentAuthorizationViewController:(PKPaymentAuthorizationViewController *)controller didSelectPaymentMethod:(PKPaymentMethod *)paymentMethod completion:(void (^)(NSArray<pkpaymentsummaryitem *> * _Nonnull))completion{

//支付银行卡回调,如果需要根据不同的银行调整付费金额,可以实现该代理

completion(summaryItems);

}</pkpaymentsummaryitem *>

送货地址回调,已弃用

 

 

-(void)paymentAuthorizationViewController:(PKPaymentAuthorizationViewController *)controller didSelectShippingAddress:(ABRecordRef)address completion:(void (^)(PKPaymentAuthorizationStatus, NSArray<pkshippingmethod *> * _Nonnull, NSArray<pkpaymentsummaryitem *> * _Nonnull))completion{

//送货地址回调,已弃用

}</pkpaymentsummaryitem *></pkshippingmethod *>

付款成功苹果服务器返回信息回调,做服务器验证

1

 

-(void)paymentAuthorizationViewController:(PKPaymentAuthorizationViewController *)controller

didAuthorizePayment:(PKPayment *)payment

completion:(void (^)(PKPaymentAuthorizationStatus status))completion {

PKPaymentToken *payToken = payment.token;

//支付凭据,发给服务端进行验证支付是否真实有效

PKContact *billingContact = payment.billingContact;     //账单信息

PKContact *shippingContact = payment.shippingContact;   //送货信息

PKContact *shippingMethod = payment.shippingMethod;     //送货方式

//等待服务器返回结果后再进行系统block调用

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

//模拟服务器通信

completion(PKPaymentAuthorizationStatusSuccess);

});

}

支付完成回调

 

-(void)paymentAuthorizationViewControllerDidFinish:(PKPaymentAuthorizationViewController *)controller{

[controller dismissViewControllerAnimated:YES completion:nil];

}

#import “ViewController.h”
#import <PassKit/PassKit.h>
@interface ViewController ()<PKPaymentAuthorizationViewControllerDelegate>

@end

@implementation ViewController

– (void)viewDidLoad {
[super viewDidLoad];

//1、判断当前设备是否支持苹果支付

// 2、判断是否添加银行卡

if (![PKPaymentAuthorizationViewController class]) {
//PKPaymentAuthorizationViewController需iOS8.0以上支持
NSLog(@”操作系统不支持ApplePay,请升级至9.0以上版本,且iPhone6以上设备才支持”);
return;
}
else if (![PKPaymentAuthorizationViewController canMakePayments]) {

NSLog(@”当前设备不支持applepay”);

}
//PKPaymentNetworkChinaUnionPay  银联卡 。PKPaymentNetworkVisa vsa 卡
//检查用户是否可进行某种卡的支付,是否支持Amex、MasterCard、Visa与银联四种卡,,根据自己项目的需要进行检测
else if (![PKPaymentAuthorizationViewController canMakePaymentsUsingNetworks:@[PKPaymentNetworkChinaUnionPay,PKPaymentNetworkVisa]])
{
// 如果没有添加银行卡,创建一个跳转按钮,跳转到添加银行卡的界面
PKPaymentButton *button=[PKPaymentButton buttonWithType:PKPaymentButtonTypeSetUp style:PKPaymentButtonStyleWhiteOutline];
button.center=self.view.center;
[self.view addSubview:button];
[button addTarget:self action:@selector(jumpAddBank) forControlEvents:UIControlEventTouchUpInside];

}
else
{
// 创建一个够买按钮,当用户点击按钮时,购买一个商品
PKPaymentButton *button=[PKPaymentButton buttonWithType:PKPaymentButtonTypeBuy style:PKPaymentButtonStyleBlack];
button.center=self.view.center;
[self.view addSubview:button];
[button addTarget:self action:@selector(clickBuy) forControlEvents:UIControlEventTouchUpInside];
}

}
#pragma mark – 点击去购买
-(void)clickBuy
{

// 1、创建一个支付请求
PKPaymentRequest *request=[[PKPaymentRequest alloc]init];
// 配置支付请求
//1.1 配置商家ID
request.merchantIdentifier=@”merchant.com.cym.weiliaopay”;

//1.2 配置国家代码,以及货币代码
request.countryCode=@”CN”;
request.currencyCode=@”CNY”;
// 1.3 支付的银行卡
request.supportedNetworks=@[PKPaymentNetworkChinaUnionPay,PKPaymentNetworkVisa];

// 1.4配置商户的处理方式//设置支持的交易处理协议,3DS必须支持,EMV为可选,目前国内的话还是使用两者吧
request.merchantCapabilities=PKMerchantCapability3DS|PKMerchantCapabilityEMV;

// 1.5 配置购买的商品列表
NSDecimalNumber *price=[NSDecimalNumber decimalNumberWithString:@”0.01″];
PKPaymentSummaryItem *item=[PKPaymentSummaryItem summaryItemWithLabel:@”汽车保养” amount:price];
request.paymentSummaryItems=@[item];

//配置请求的附加项
//1、是否显示发票收货地址 。显示哪些选项
//    request.requiredBillingAddressFields=PKAddressFieldAll;
//    // 2、是否显示快递地址,显示哪些选项
//    request.requiredShippingAddressFields=PKAddressFieldAll;

//2、 验证用户的支付授权

PKPaymentAuthorizationViewController *PayVC=[[PKPaymentAuthorizationViewController alloc]initWithPaymentRequest:request];

PayVC.delegate=self;

[self presentViewController:PayVC animated:YES completion:nil];

}
#pragma mark  -代理方法
//如果当用户授权成功,就会调用这个方法
/*
参数一:授权控制器
参数二:支付对象
参数三:系统给定的一个回调代码块,我们需要执行这个代码块,来告诉系统当前的的支付状态是否成功
*/
– (void)paymentAuthorizationViewController:(PKPaymentAuthorizationViewController *)controller
didAuthorizePayment:(PKPayment *)payment
completion:(void (^)(PKPaymentAuthorizationStatus status))completion
{

NSLog(@”token=%@”,payment.token);
// 一般在此外,拿到支付信息,发送给服务器处理,处理完毕之后,服务器返回一个状态,告诉客户端,是否支付成功,然后由客户端进行处理
BOOL isSuccess=YES;

if (isSuccess)
{
completion(PKPaymentAuthorizationStatusSuccess);
}
else
{
completion(PKPaymentAuthorizationStatusFailure);
}

}

#pragma mari 当用户授权成功,或者取消授权时调用
– (void)paymentAuthorizationViewControllerDidFinish:(PKPaymentAuthorizationViewController *)controller
{

[self dismissViewControllerAnimated:YES completion:nil];

}

#pragma mark – 添加银行卡界面
-(void)jumpAddBank
{
// 跳转到添加银行卡界面
PKPassLibrary *pl=[[PKPassLibrary alloc]init];

[pl openPaymentSetup];

}
– (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}

云计算从产业发展、公共服务和生活领域,改变着我们的生活

云计算产业发展与智慧城市建设相辅相成,云计算技术在工业、交通、能源、医疗、市政等经济社会各个领域支撑城市的智慧发展。通过技术创新提高城市的综合管理效率和公共服务水平,让城市运营发展的更加智慧。同时智慧城市也在孕育和催化云计算典型应用的落地和推广,为云计算产业发展不断拓展广阔的空间。

今天,云计算已经从纸上蓝图发展成为实实在在的大产业,革命性的将大数据、大宽带、大平台、大服务捆绑在一起,孕育着广阔的产业变革,深刻改变着信息产业发展格局和我们的生产生活方式。具体表现在三个方面:

产业发展领域:云计算加速了产业优化升级步伐,越来越多的企业通过大规模部署云计算在推动战略性变革,实现更精准的决策和更深入的协作方面获得企业核心竞争优势。借助互联网、云计算技术,实现多业态融合,成为产业结构调整升级新方向,*大的促进中小企业创新创业和全社会信息化水平提升。

公共服务领域:云计算提升了服务水平和管理效率。随着云计算和大数据技术在智慧城市建设、社区精细管理、疾病预防和治疗、食品药品安全监管、环境污染监测等领域的逐渐应用,社会管理效率、公共服务水平和人民幸福感将得到*大的提升。

个人生活领域:云计算使工作更加高效,生活更加快乐。随着云计算、大数据时代的到来,云办公、云笔记、云视频、云记帐等被广泛应用,可穿戴设备随时关注着我们的健康。基于大数据的反馈经济,让我们生活的更加便捷。

随着多元化的发展,思想文化的交流,社会也变得越来越无序。所以更需要借助云计算、大数据等新一代信息技术手段,面向未来,构建我们的现代市场体系,宏观调控体系,开放型经济体系等等。这都给云计算产业的发展孕育提供了更大的空间。

python之有参装饰器

python之有参装饰器

装饰器
装饰器补充
有参装饰器
迭代器
生成器
装饰器补充
#偷梁换柱:即将原函数名指向的内存地址偷梁换柱成了wrapper函数,所以应该将wrapper做的跟原函数一样才行

from functools import wraps
def outer(func):
@wraps(func)
def wrapper(*args,**kwargs):
res = func(*args,**kwargs) #res=index(1,2)
return res
#将原函数的属性赋值给wrapper函数
#函数wrapper.__name__=原函数.__name__
#函数wrapper.__doc__=原函数.__doc__
#wrapper.__name__ =func.__name__
#wrapper.__doc__=func.__doc__
return wrapper
@outer #index=outer(index)
def index(x,y):
”’这个是主页功能”’
print(x,y)
print(index.__name__)
print(index.__doc__)

index(1,2) #wrapper(1,2)

有参装饰器
一、知识储备
由于语法糖@的限制,outer函数只能有一个参数,并且该参数只用来接收被装饰对象的内存地址

def outer(func):
def wrapper(*args,**kwargs):
res = func(*args,**kwargs)
return res
return wrapper

@outer #index = outer(index) #index==>wrapper
def index(x,y):
print(x,y)

#偷梁换柱之后
#index的参数是什么样子,wrapper的参数就应该是什么样
#index的返回值什么样子,wrapper的返回值就应该是什么样子
#index的属性什么样子,wrapper的属性就应该是什么样子==>from functools import wraps

傻瓜1:

def auth(func,db_type):
def wrapper(*args,**kwargs):
name = input(‘your name:>>’).strip()
pwd = input(your password:>>’).strip()
if db_type == ‘file’:
#从文件中取账号密码进行验证
if name ==’egon’ and pwd == ‘123’:
print(‘基于文件的验证’)
res = func(*args,**kwargs)
return res
else:
print(‘user or password error’)
elif db_type == ‘mysql’:
print(‘基于mysql的验证’)
elif db_type == ‘ldap’:
print(‘基于ldap的验证’)
else:
print(‘不支持db_type’)
return wrapper

@auth #账号密码来源是文件
def index(x,y):
print(‘index->>%s:%s’ %(x,y))

@auth #账号密码的来源是数据库
def home(name):
print(‘home->>%s’ % name)

@auth #账号密码的来源是ldap
def transfer():
print(‘transfer’)

index = auth(index,’file’)
home = auth(home,’mysql’)
transfer = auth(transfer,’ldap’)

傻瓜2:

def auth(db_type):
def deco(func):
def wrapper(*args,**kwargs):
name = input(‘your name:>>’).strip()
pwd = input(‘your password:>>’).strip()
if db_type == ‘file’:
#从文件中取账号密码进行验证
if name == ‘egon’ and pwd == ‘123’:
print(‘基于文件的验证’)
res = func(*args,**kwargs)
return res
else:
print(‘user or password error’)
elif db_type == ‘mysql’:
print(‘基于mysql的验证’)
elif db_type == ‘ldap’:
print(‘基于ldap的验证’)
else:
print(‘不支持db_type’)
return wrapper
return deco

deco = auth(db_type = ‘file’)
@deco #账号密码来源是文件
def index(x,y):
print(‘index->>%s:%s’ %(x,y))

deco = auth(db_type = ‘mysql’)
@deco #账号密码的来源是数据库
def home(name):
print(home–>%s’ %name)

deco = auth(db_type = ‘ldap’)
@deco #账号密码的来源是ldap
def transfer():
print(‘transfer’)

index(1,2)
home(‘egon’)
transfer()

语法糖

def auth(db_type):
def deco(func):
def wrapper(*args,**kwargs):
name = input(‘your name>>:’).strip()
pwd = input(‘your password>>:’).strip()
if db_type == ‘file’:
#从文件中取账号密码进行验证
if name == ‘egon’ and pwd ==’123′:
print(‘基于文件的验证’)
res = func(*args,**kwargs)
return res
else:
print(‘user or password error’)
elif db_type == ‘mysql’:
print(‘基于mysql的验证’)
elif db_type == ‘ldap’:
print(‘基于ldap的验证’)
else:
print(‘不支持db_type’)
return wrapper
return deco

@auth(db_type = ‘file’) #@dec0 #index = deco(index) #index=wrapper
def index(x,y):
print(‘index->>%s:%s’ %s (x,y))

@auth(db_type = ‘mysql’) #账号密码的来源是数据库
def home(name):
print(‘home–> %s’ %name)

@auth(db_type = ‘ldap’) #账号密码的来源是ldap
def transfer():
print(‘transfer’)

index(1,2)
home(‘egon’)
transfer()

有参装饰器模板

def 有参装饰器(x,y,z):
def outer(func):
def wrapper(*args,**kwargs):
res = func(*args,**kwargs)
return res
return wrapper
return outer

@有参装饰器(1, y =2 , z= 3)
def 被装饰对象():
pass

迭代器
什么是迭代求
迭代器指的是迭代取值的工具,迭代是一个重复的过程,每次重复都是基于上一次的结果而继续的,单纯的重复并不是迭代。
2.为何要有迭代
迭代器是用来取值的工具,而涉及到把多个值循环取出来的类型有:
列表、字符串、元组、自ID以、集合、打开文件
l = [‘egon’,’liu’,’alex’]
i = 0
while i < len(l):
print(l[i])
i+=1

上述迭代取值的方式只适用于有索引的数据类型:列表、字符串
为了解决基于索引迭代器取值的局限性,python必须提供一种能够不依赖索引的取值方式,这就是迭代器

3.如何用迭代器

可迭代对象:但凡内置有__iter__方法的都称之为可迭代的对象
s1 = ”
s1.__iter__()
l =[]
l.__iter__()
d = {‘a’:1}
d.__iter__()
set1 ={1,2,3}
set1.__iter__()
with open(‘a.txt’,mode = ‘w’,encoding=’utf-8′) as f:
f.__iter__()
f.__next__()

调用可迭代对象下的__iter__方法会将其转换成迭代器对象

d = {‘a’:1,’b’:2,’c’:3}
d_iterator = d.__iter__()
print(d_iterator)
print(d_iterator.__next__())
print(d_iterator.__next__())
print(d_iterator.__next__())
print(d_iterator.__next__()) # 抛出异常StopIteration 迭代器取值取干净了

l = [1,2,3,4,5]
l_iterator = l.__iter__()
while True:
try:
print(l_iterator.__next__())
except StopIteration:
break

4.可迭代对象与迭代器对象详解
可迭代对象(‘可以转换成迭代器的对象’):内置有__iter__方法对象
可迭代对象.iter():得到迭代器对象

可迭代对象:字符串、列表、元组、字典、集合、文件列表

迭代器对象:文件对象

s1 = ”
s1.__iter__()
l =[]
l.__iter__()
d = {‘a’:1}
d.__iter__()
set1 ={1,2,3}
set1.__iter__()
with open(‘a.txt’,mode = ‘w’,encoding=’utf-8′) as f:
f.__iter__()
f.__next__()

迭代器:内置有__next__方法并且内置有__iter__方法的对象
迭代器对象.next():得到迭代器的下一个值
迭代器对象.iter():得到迭代器本身,说白了掉跟没调一样

dic = {‘a’:1,’b’:2}
dic_iterator = dic.__iter__()
print(dic_iterator is dic_iterator.__iter__())

for 循环的工作原理:for循环可以称之为迭代器循环

for x in 迭代器对象.__iter__():
1
d = {‘a’:1,’b’:2,’c’:3}
d_iterator = d.__iter__()
while True:
try:
print(d_iterator.__next__())
except StopIteration:
break

d.iter() 得到一个迭代器对象
迭代器对象.next()拿到一个返回值,然后将该返回值赋值给k
循环往复上一步骤,直到抛出StopIteration异常 for循环会捕捉异常然后结束循环

for k in d:
print(k)
with open(‘笔记’,mode = ‘rt’,encoding=’utf-8′) as fp:
for line in fp:
print(line)

list(‘hello’) #原理同for循环
1
生成器
如何得到自定义的迭代器:
在函数内一旦存在yield关键字,调用函数并不会以执行函数体代码,会返回一个生成器对象,生成器即自定义的迭代器

def func():
print(‘first’)
yield 1
print(‘second’)
yield 2
print(‘third’)
yield 3
print(‘fourth’)

g = func()
print(g)

生成器就是迭代器
g.__iter__()
g.__next__()

会触发函数体代码的运行,然后遇到yield停下来,将yield后的值当做本次调用的结果返回

res1 = g.__next__()
print(res1)

res2 = g.__next__()
print(res2)

res3 = g.__next__()
print(res3)

res4 = g.__next__()

应用案例

def my_range(start,stop,step=1):
print(‘start…’)
while start < stop:
start+=step
yield start
print(‘end…’)

g = my_range(1,5,2)
print(next(g))
print(next(g))
print(next(g))

论python的多级引用机制

论python的多级引用机制

一、多级引用在不同目录层级的调用权限
主目录就叫main吧

main/
—-main.py
—-pkg1/
——–a1.py
——–a2.py
——–a3.py
—-pkg2/
——–b1.py

a1.py中

from .a2 import usefunc

def qqfunc():
usefunc()

a3.py中

from a1 import qqfunc
qqfunc()

main.py中

from pkg1.a1 import qqfunc
qqfunc()

可以在main下执行main.py
但是不能在pkg1目录下执行a3.py
因为此时cwd在pkg1,不能解析.a1文件。
相对引用要求cwd在相对引用的文件的上级目录(上多少级就无所谓了)。

相反的我们把a1略作修改
a1.py中

from a2 import usefunc

def qqfunc():
usefunc()

去掉了.
此时可以在pkg1目录下执行a3.py
但不能在main下执行main.py
因为去掉.之后采用的是module名直接检索,
只能在cwd=pkg1时才能搜到a2这个文件。
cwd=main时搜不到。

然后是重名的情况。
重名时候优先满足cwd下的,因为cwd是sys.path[0]。

二、多级引用包装成属性的形式
核心需求
怎么才能自己写一个package。比如文件夹是/home/aa/bb/cc/dd.py。
/home下有一个t.py。
在t.py里面import aa。
就可以直接像访问property一样,调用 aa.bb.cc.dd.somefunc()。

实验
t.py内容

import aa
aa.bb.cc.dd.somefunc()

dd.py内容

def somefunc():
print(‘hello’)

aa/__init__.py添加

import bb
报错ModuleNotFoundError: No module named ‘bb’

改为添加

import .bb
报错ModuleNotFoundError: No module named ‘bb’

改为

from . import *
报错ModuleNotFoundError: No module named ‘bb’

改为

from . import bb
t.py中成功找到了aa.bb,但是报错 module ‘aa.bb’ has no attribute ‘cc’

由是可知

相对引用package需要采用from 相对位置 import package_name的方式。因为相对位置只能写在from和import中间。
from . import * 只会检索当前目录下的module,而不会导入package。
继续实验
同样地在/aa/bb/__init__.py里添加

from . import cc
t.py中成功找到了aa.bb.cc,但是报错
AttributeError: module ‘aa.bb.cc’ has no attribute ‘dd’

同样地在/aa/bb/cc/__init__.py里添加

import .dd
报错SyntaxError: invalid syntax

改成

import dd
报错ModuleNotFoundError: No module named ‘dd’

改成

from . import dd
t.py成功执行。

总之一句话,相对引用,无论import后面接package还是module,都得用
from … import的格式。

一级目录下可以直接相对引用深层内容
如果在/aa/__init__.py里面这样写

from .bb.cc.dd import somefunc

在t.py里面

import aa
aa.somefunc()
aa.bb.cc.dd.somefunc()

依然可以执行成功

但是显然,子目录每多一个函数,都需要在aa/init.py里面加,也太累了。

重名情况
假设/aa/hh.py下

def somefunc():
print(‘nono’)

在/aa/__init__.py下

from .bb.cc.dd import somefunc
from .hh import somefunc

t.py下

import aa
aa.somefunc()
aa.bb.cc.dd.somefunc()

会输出

nonono
hello

调换init里面的调用顺序,两行都是hello。
可以看出,同一个__init__.py 中的重名情况,会按照引用顺序,
后引用的覆盖前者。

文件操作

文件操作

 

课:文件的常规操作 讲课老师:风陨老师

2021/4/16

一、文件的打开与关闭,有打开就有关闭

​ 1、 文件操作的步骤:(1)、打开文件

 

​ (2)、操作文件

 

​ (3)、关闭文件

 

​ 2,文件目录等级: (1)、*对路径:*对路径就是当前文件的准确位置

 

​ (2)、相对路径:①同级路径,调用方式 ‘.’一个点

 

​ ②不同级路径,上级’…’两个点

 

​ 3、打开文件:open() 需要三个参数: (1)、需要打开的文件名

 

​ (2)、操作方式

 

​ (3)、编码指定

 

open_file = open(“youxi.py”, ‘r’,encoding=’utf8’) # 打开文件

print(read_open)

 

 

open_file.close()    # 关闭文件

 

二、文件的访问方式

1、r 以读取的方式打开文件,文件的游标默认放在文件的开头

 

read_open = open(“youxi.py”, ‘r’,encoding=’utf8’)  # 返回文件对象

 

 

read_open.close() # 关闭文件

 

注意:读取r方式打开的文件只能读,不能修改或写入

 

 

2、w 写入的打开方式,如果该文件已存在则将其覆盖。如果该文件不存在,则创建新文件

 

Write_open = open(“youxi.py”, ‘w’,encoding=’utf8’)

 

pritn(Write_open)

 

#如果没有youxi.py文件,就会在同级重新再建立一个新的 youxi.py 文件

#如果有youxi.py文件 ,就会被覆盖

 

Write_open.close()

 

注意:以w写入方式打开的文件会被清空

 

3、a 追加的方式打开文件,如果该文件已存在,游标默认放在文件的结尾,新的内容会被写入到已 有内容的后面。如果该文件不存在,则创建新的文件进行写入。

 

addto_open = open(“youxi.py”, ‘a’,encoding=’utf8’)

 

 

print(addto_open.write(‘游戏结束’))  #操作文件

 

#如果youxi.py文件存在,’游戏结束’就会被写入到youxi.py文件已有内容的*后面

#如果youxi.py文件不存在,就会在同级新建youxi.py文件,再写入’游戏结束’

 

 

addto_open.close()

 

注意:以追加的方式打开文件不可读取

 

小知识:

(1)r+/w+/a+,在原功能的基础上增加读写的功能,但是想要使用相应功能,光标位置调整至文件开头

 

(2)rb/wb/ab,是以二进制的方式对文件进行操作,不指定编码

 

(3)rb+/wb+/ab+,以二进制的方式打开文件,在原功能的基础上增加读写的功能,但是想要使用相应功能,光标位置调整至文件开头

 

三、读取写入文件相关操作

1、read() 读取指定数量内容(如果传入数值可控制读取数据多少)

 

read_open = open(“youxi.py”, ‘r’,encoding=’utf8’)

 

pritn(read_open.read())      #对文件进行读取操作

#默认读取所有数据

 

 

pritn(read_open.read(100))   #对文件进行读取操作

#传值是100就读取100个数据

 

 

read_open.close()

 

2 readline() 读取一行的内容

 

readline_open = open(“youxi.py”, ‘r’,encoding=’utf8’)

 

print(redaline_open.readline()) #对文件进行读取一行操作

 

#默认读取*行的数据

 

 

readline_open.close()

 

 

3、readlines() 读取多行的内容

 

readlines_open = open(“youxi.py”, ‘r’,encoding=’utf8’)

 

print(readlines_open.readlines())      #对文件进行多行读取操作

 

#默认读取所有数据

 

 

print(readlines_open.readlines(100))

 

#传值为100就读取100行数据

 

readlines_open.close()

 

 

4、write() 写入内容

 

Write_open = open(“youxi.py”, ‘w’,encoding=’utf8’)

 

pritn(Write_open.wite(‘游戏结束…’)) #对文件进行写入操作

 

#在youxi.py文件中已有的内容全部被覆盖写入’游戏结束’此时的youxi.py文件只有’游戏结束…’内容

 

 

Write_open.close()

 

5、writelines() 写入多行内容

 

Writelines_open = open(“youxi.py”, ‘w’,encoding=’utf8’)

 

print(witelines_open.witelines(‘我将写入多行代码,这是*行\n这是第二行\n这是第三行’))

 

#在youxi.py文件中已有的内容全部被覆盖写入’我将写入多行代码,这是*行\n这是第二行\n这是第三行’此时的youxi.py文件只有’我将写入多行代码,这是*行\n这是第二行\n这是第三行’。三行代码内容

 

 

witelines_open.close

 

 

6、flush() 立即刷新缓冲区域(手动保存)

 

flush_open = open(“youxi.py”, ‘r+’, encoding=’utf8′)

 

print(flush_open.flush())                           #对文件进行刷新手动保存操作

 

#flush用来刷新缓冲区的,把缓冲区中的数据立刻写入文件,同时清空缓冲区。

 

flush_open.close()

 

 

7、tell() 获取游标位置

 

tell_open = open(“youxi.py”, ‘r+’, encoding=’utf8′)

 

print(tell_open.tell())                            #查找游标位置

 

#使用tell获取文件游标的当前位置:1、用R和W模式打开的文件游标默认在开头,也就是0

#                           2、用a追加模式打开的文件游标默认在结尾就是2

 

 

 

tell_open.close()

 

8、seek() 调整游标位置

 

seek_open = (“youxi.py”, ‘rb’)

 

print(seek_open.seek())

#位置调整:1、输入0时游标调整到文件开头的位置

#          2、输入为1时游标调整到游标当前位置

#          3、输入2时,游标位置调整到*后

 

 

seek_open.close()

 

#注意:调整位置是以二进制单位读取数据,所以打开文件的方式是二进制,rb , wb,ab,在此情况下不用指定传编码

 

9、 偏移量:

 

offset_open = (“youxi.py”, ‘rb’)

 

print(offset_open.seek(5, 0))    # 其中5指的就是偏移量,0为开头,把游标调到开头完后移5

 

 

#          1、输入0时游标调整到文件开头的位置

#          2、输入为1时游标调整到游标当前位置

#          3、输入2时,游标位置调整到*后

 

 

offset_open.close()

 

 

四、实现文件备份

 

old_fileName = input(‘请输入需要拷贝的的文件\n’)               #设置想要拷贝的文件

 

old_file = open(old_fileName, ‘r’, encoding=’utf8′)        #打开想要拷贝的文件

 

if old_file:                                               #如果文件能打开

 

suffix = old_fileName.rfind(‘.’)                       #查看后缀名字

 

if suffix > 0:                                         #如果有后缀名

 

new_suffix = old_fileName[suffix:]                 #提取后缀名

# print(new_suffix)

 

new_file = old_fileName + ‘[拷贝]’ + new_suffix         #拷贝文件

# print(suffix)

new_file_open = open(new_file, ‘w’, encoding=’utf8′)    #打拷贝的文件

 

for eachline in old_file.readlines():              #读取每一行

 

new_file_open.write(eachline)                      #写入每一行

 

 

old_file.close()                                            #关闭旧文件

new_file_open.close()                                       #关闭新文件

 

五、os 模块的目录及文件操作

import os             #调用os模块为内置模块

 

 

1、os.getcwd()  显示当前路径

 

print(os.getcwd())

 

 

2、os.listdir() 显示同级目录下的所有文件

 

print(os.listdir())

 

 

3、os.chdir() 改变当前路径

 

print(os.getcwd())  #当前路径在现在目录的位置

print(os.chdir(‘输入需要改变到哪一个目录’))

print(os.getcwd())  #当前路径变成输入后的路径

 

 

4、os.mkdir() 创建新文件夹

 

print(os.mkdir(‘../输入新文件夹名’))

 

 

5、os.rmdir() 删除指定目录,且此目录必须为空。否则报错

 

print(os.rmdir(‘../输入要删除的空文件夹’))

 

 

6、os.system() 执行系统指令

 

print(os.system(‘输入指令英文名,如help’))

 

 

7、os.remove() 指定路径删除,且只能是文件不能是文件夹

 

print(os.remove(‘输入要删除路径中的文件名’))

 

 

8、os.rename(‘old’,’new’) 对一个旧的文件重新命名

 

print(os.rename(‘old_file.py’, ‘new_file.py’))

 

 

六、os.path模块操作

1、os.path.join   目录和文件名合成一个路径

 

print(os.path.join(‘文件夹名/dfs/文件夹名’,’文件名字’))

 

 

2、os.path.basename() 返回文件名

 

print(os.path.basename(‘输入要返回位置的文件名’))

 

 

3、os.path.abspath()  查看*对路径

 

print(os.paht.abspath(‘输入要返回*对路径的文件名’))

 

 

4、os.path.relpath()  相对路径

 

python(os.path.relpath(‘文件名’, ‘同级或者不同级文件夹名’))

 

 

5、os.path.getsize()     查看文件大小

 

print(os.path.getsize(‘输入要查看大小的文件’))

 

 

 

6、os.path.getctime()   查询文件创建时间

 

print(os.path.getctime(‘输入需要查看的文件名’))

 

 

 

7、os.path.getmtime()    查询*近修改时间

 

print(os.path.getmtime(‘输入要查询的文件名’))

 

 

8、os.path.getatime()  查询*近访问时间

 

print(os.path.getatime(‘输入要查询的文件名’))

 

 

 

9、os.path.exists()    判断路径中是否存在想要的文件

 

print(os.path.exists(‘输入文件名’))

 

 

10、os.path.isdir()    判断是否是文件目录

 

print(os.path.isdir(‘输入文件名’))

 

 

11、os.path.isfile()   判断是否为文件

 

print(os.path.isfile(‘输入文件名’))

 

 

12、os.path.isabs()    判断是否为*对路径

 

print(os.path.isabs(‘输入文件名’))

 

七、上下文管理器

with open(‘文件名’,’r’,encoding=’编码方式’) as a,\

open(‘文件名’,’r’,encoding=’编码方式’) as b,\

open(‘文件名’,’r’,encoding=’编码方式’) as c:

a = a.readlines()

b = b.readlines()

c = c.readlines()

 

print(a, b, c)

 

小知识:上下文管理器实现原理

1、with open() as a:  自动执行打开文件关闭的过程(一个或多个)

2、a:  变量接收名,后面通过它对打开文件执行读,写,追加的相应的操作

3、内部代码也可执行其它操作

4、内部代码执行结束时,自动执行关闭文件操作

 

八、导,自定义函数路径

import sys   #导包

sys.path     #查看所有能导包的路径

 

sys.path.append(‘添加需要导包的路径’)  #如果想导的路径不在导包目录中就进行添加后即可导路径

 

 

 

from 准确的路径 import 文件内容        #路径导包

 

print(文件内容)                      #测试是否成功导入

 

摄氏度转换表

摄氏度转换表

 

 

## python生成华氏度-摄氏度转换表

 

#输入2个正整数lower和upper(lower≤upper≤100),请输出一张取值范围为[lower,upper]、且每次增加2华氏度的华氏-摄氏温度转换表。

#温度转换的计算公式:C=5×(F−32)/9,其中:C表示摄氏温度,F表示华氏温度。

upper=input()

lower=input()

upper=eval(upper);lower=eval(lower)

if upper<lower:

print(“输入有误,请重新输入”)

else:

print(“下面是温度转换表”);i=lower

while i<upper:

print(“{:d}–{:>6.1f}”.format(i,5*(i-32)/9))

i=i+2

 

 

 

思路:首先判断输入数据是否有误(例如大小关系等)

若输入无误则进入转换表的打印,首先打印如下是“温度转换表”使得程序更加贴切人意,再使用占位符以及while循环对输入的温度区间遍历并且运用算法转换。