Reputation: 63
I've been trying this code and getting this message from the console:
usage: Experimental.py [-h] [-p PORT] {client,server}
Experimental.py: error: the following arguments are required: role
I can't decide what's wrong, this is the code:
import argparse, socket
from datetime import datetime
MAX_BYTES = 65535
def server(port):
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(('127.0.0.1', port))
print('Listening at {}'.format(sock.getsockname()))
while True:
data, address = sock.recvfrom(MAX_BYTES)
text = data.decode('ascii')
print('The client at {} says {!r}'.format(address, text))
text = 'Your data was {} bytes long'.format(len(data))
data = text.encode('ascii')
sock.sendto(data, address)
def client(port):
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
text = 'The time is {}'.format(datetime.now())
data = text.encode('ascii')
sock.sendto(data, ('127.0.0.1', port))
print('The OS assigned me the address{}'.format(sock.getsockname()))
data, address = sock.recvfrom(MAX_BYTES) # Danger!
text = data.decode('ascii')
print('The server {} replied {!r}'.format(address, text))
if __name__ == '__main__':
choices = {'client': client, 'server': server}
parser = argparse.ArgumentParser(description='Send and receive UDP locally')
parser.add_argument('role', choices=choices, help='which role to play')
parser.add_argument('-p', metavar='PORT', type=int, default=1060, help='UDP port (default 1060)')
args = parser.parse_args()
function = choices[args.role]
function(args.p)
Upvotes: 1
Views: 771
Reputation: 6554
The program is using the argparse module's ArgumentParser
class, which assumes by default that positional arguments are required, so you can't omit them as you have. The argparse tutorial offers a good definition of a positional argument:
[A positional argument is] named so because the program should know what to do with the value, solely based on where it appears on the command line. This concept is more relevant to a command like cp, whose most basic usage is cp SRC DEST. The first position is what you want copied, and the second position is where you want it copied to.
In this case, when calling Experimental.py
, you've left out the positional argument named role
, which is defined near the end of your program:
parser.add_argument('role', choices=choices, help='which role to play')
(Because the first argument ('role'
) doesn't start with a -
(like -p
), add_argument
registers it as a positional argument.)
The choices
keyword argument to add_argument
requires an iterable containing the possible values to supply, so the author of the program passes choices
, a dictionary defined as:
choices = {'client': client, 'server': server}
This is actually pretty clever; iterating over a dictionary yields the keys, so argparse allows client
and server
as values for role
. So, to fix this error, you should pass either client
or server
as an argument to the program, thereby supplying a value for role
. Even better, you can check out the argparse tutorial. (I hate telling people to read the manual, but I think it might be helpful)
tl;dr: instead of:
$ python3 Experimental.py
you should try one of the following:
$ python3 Experimental.py server
$ python3 Experimental.py client
Upvotes: 2