-3

How would you convert Python 2.7 to Python 3.6.5? Here, I am trying to query a set of NTP time servers and determine which one is the outlier.

It is probably a few simple changes but I am unsure..

from contextlib import closing
from socket import socket, AF_INET, SOCK_DGRAM
import sys
import struct
import time

NTP_PACKET_FORMAT = "!12I"
NTP_DELTA = 2208988800L # 1970-01-01 00:00:00
NTP_QUERY = b'\x1b' + 47 * '\0'  

def ntp_time(host="pool.ntp.org", port=123):
    with closing(socket( AF_INET, SOCK_DGRAM)) as s:
        s.sendto(NTP_QUERY, (host, port))
        msg, address = s.recvfrom(1024)
    unpacked = struct.unpack(NTP_PACKET_FORMAT,
            msg[0:struct.calcsize(NTP_PACKET_FORMAT)])
    return unpacked[10] + float(unpacked[11]) / 2**32 - NTP_DELTA

if __name__ == "__main__":
    print time.ctime(ntp_time()).replace("  "," ")
Gil Hamilton
  • 11,973
  • 28
  • 51
Hosep
  • 39
  • 4
  • 3
    Have you tried running your code on the 3.6.5 interpreter? If so what errors/warnings do you get. The question is much too broad to be answered by anyone on this site. – vividpk21 Aug 30 '18 at 16:42
  • IMHO this question isn't too broad, but you should also show us your attempt at a Python 3 version, and explain the errors that you get when you try to run it on Python 3.6. The 2to3 tool can help with the conversion, but this code will need a few more tweaks, due to the Python 3 way of handling bytes. – PM 2Ring Aug 30 '18 at 16:52
  • I am getting a syntax error on 2208988800L – Hosep Aug 30 '18 at 16:55
  • Yes, that old long integer format doesn't exist in Python 3. You will need to learn the basic differences between Python 2 & 3 to do this conversion correctly. The 2to3 program should be part of your Python installation, and it can convert stuff like that. You might have a couple of different versions of 2to3, so make sure you run the latest one! – PM 2Ring Aug 30 '18 at 17:03
  • After I change print(), I get error, _TypeError: a byte-like object is required, not 'str'_ on.. `s.sendto(NTP_QUERY, (host, port))` & `print time.ctime(ntp_time()).replace(" "," ")` – Hosep Aug 30 '18 at 17:16

2 Answers2

1

Here's a version of your code with minimal changes that runs correctly on Python 3.6. Apart from fixing the prints and that long integer literal, which I did automatically using 2to3, I also changed NTP_QUERY to a bytes string.

from contextlib import closing
from socket import socket, AF_INET, SOCK_DGRAM
import sys
import struct
import time

NTP_PACKET_FORMAT = "!12I"
NTP_DELTA = 2208988800 # 1970-01-01 00:00:00
NTP_QUERY = b'\x1b' + bytes(47)

def ntp_time(host="pool.ntp.org", port=123):
    with closing(socket( AF_INET, SOCK_DGRAM)) as s:
        s.sendto(NTP_QUERY, (host, port))
        msg, address = s.recvfrom(1024)
    unpacked = struct.unpack(NTP_PACKET_FORMAT,
            msg[0:struct.calcsize(NTP_PACKET_FORMAT)])
    return unpacked[10] + unpacked[11] / 2**32 - NTP_DELTA

if __name__ == "__main__":
    print(time.ctime(ntp_time()).replace("  "," "))

There are a few more things that can be done to take advantage of Python 3 features. Here's a more streamlined version. We don't need contextlib, since a Python 3 socket can be used directly in a with statement. And we don't need struct, as a Python 3 int has a from_bytes method.

from socket import socket, AF_INET, SOCK_DGRAM
import time

NTP_DELTA = 2208988800 # 1970-01-01 00:00:00
NTP_QUERY = b'\x1b' + bytes(47)

def ntp_time(host="pool.ntp.org", port=123):
    with socket( AF_INET, SOCK_DGRAM) as s:
        s.sendto(NTP_QUERY, (host, port))
        msg, _ = s.recvfrom(1024)
    return int.from_bytes(msg[-8:], 'big') / 2 ** 32 - NTP_DELTA

if __name__ == "__main__":
    print(time.ctime(ntp_time()))
PM 2Ring
  • 54,345
  • 6
  • 82
  • 182
0

The L is not present in python3, that is the first thing you need to change. Convert 2208988800L to 2208988800 read more here

Second, you should rewrite your print command in a print() function. read more here

U3.1415926
  • 812
  • 12
  • 30