How to use the sys module in Python with a text file - python-3.5

Let's say I have a text file, adding.txt. In there I have the following:
22
25
I have a python script, add.py which has a function to add the 22 and 24 from the text file.
def add(a, b):
return a + b
import sys # you must import "sys" to read from STDIN
lines = sys.stdin.readlines() # read in the input from STDIN
a = lines[0]
b = lines[1]
print(add(a, b)) # should give 47
How should I run this script using the sys module?
I am using Pycharm. Thank you. I want to learn how to use the sys module using text files.

def add(a, b):
return a + b
import sys # you must import "sys" to read from STDIN
lines = sys.stdin.readlines() # read in the input from STDIN
a = int(lines[0])
b = int(lines[1])
print(add(a, b)) # should give 47
Then go on the command prompt, type:
pathname of python file < pathname of text file
add.py.py < adding.txt
the whole pathnames could be added instead

Related

Calling a program with command line parameters with Pytest

This is my first time using Pytest, I have a program that is called with command line parameters, as in :
$ myprog -i value_a -o value_b
I am not sure how to use Pytest to test the output of this program. Given values of value_a and value_b, I expect a certain output that I want to test.
The Pytest examples that I see all refer to testing functions, for instance if there is a function such as:
import pytest
def add_nums(x,y):
return x + y
def test_add_nums():
ret = add_nums(2,2)
assert ret == 4
But I am not sure how to call my program using Pytest and not just test individual functions? Do I need to use os.system() and then call my program that way?
In my program I am using argparse module.
The solution is based on monkeypatch fixture. In below example myprog reads number from the file myprog_input.txt adds 2 to it and stores result in myprog_output.txt
Program under test
cat myprog.py
#!/usr/bin/python3.9
import argparse
import hashlib
def main():
parser = argparse.ArgumentParser(description='myprog')
parser.add_argument('-i')
parser.add_argument('-o')
args = parser.parse_args()
with open(args.i) as f:
input_data=int(f.read())
output_data=input_data+2
f.close()
with open(args.o,"w") as fo:
fo.write(str(output_data) + '\n')
fo.close()
with open(args.o) as fot:
bytes = fot.read().encode() # read entire file as bytes
fot.close()
readable_hash = hashlib.sha256(bytes).hexdigest();
return readable_hash
if __name__ == '__main__':
print(main())
Test
cat test_myprog.py
#!/usr/bin/python3.9
import sys
import myprog
def test_myprog(monkeypatch):
with monkeypatch.context() as m:
m.setattr(sys, 'argv', ['myprog', '-i', 'myprog_input.txt', '-o', 'myprog_output.txt'])
assert myprog.main() == 'f0b5c2c2211c8d67ed15e75e656c7862d086e9245420892a7de62cd9ec582a06'
Input file
cat myprog_input.txt
3
Running the program
myprog.py -i myprog_input.txt -o myprog_output.txt
f0b5c2c2211c8d67ed15e75e656c7862d086e9245420892a7de62cd9ec582a06
Testing the program
pytest test_myprog.py
============================================= test session starts =============================================
platform linux -- Python 3.9.5, pytest-6.2.5, py-1.10.0, pluggy-1.0.0
rootdir: /home/<username>/py
plugins: hypothesis-6.23.1
collected 1 item
test_myprog.py . [100%]
============================================== 1 passed in 0.04s ==============================================

Giving pause of second in Google text to speech using python

from gtts import gTTS
import os
import random
with open('symbols.txt', 'r') as file:
symbols = file.read().replace('\n', '')
def getunique():
for r, d, f in os.walk(path):
for file in f:
if file.endswith('.mp3'):
unique.add(file.split('.')[0])
def generate(unique):
chars = symbols
while True:
value = "".join(random.choice(chars) for _ in range(8))
if value not in unique:
language = 'en'
myobj = gTTS(text=value, lang=language, slow=True)
myobj.save("audio_captcha_training_set2/"+value+".mp3")
unique.add(value)
break
path = "C:\\Users\\DNS\\Desktop\\Audio Captcha\\Test Python code\\audio_captcha_training_set\\"
unique = set()
getunique()
for _ in range(20):
generate(unique)
Here is a code which reads a file in which there is characters from 0-9 and A-Z. This is generating audio for random 8 characters reading from file but it does not give any pause or delay while generating audio of characters. I want to add a pause of a second between each characters. Any help?

How to capture the user command, when a python script is called?

Let's say I have a python script myscript.py, which takes multiple named arguments. The user calls the script as python myscript.py --arg1 value1 --arg2 value2. How to capture this whole command (i.e. python myscript.py --arg1 value1 --arg2 value2 ) and save it to a text file "command.selfie" using the same script that the user is calling?
sys.argv is a list with all the arguments.
This will help:
import sys
command = " ".join(sys.argv)
# do whatever you want to do with command: str
You can do something like this:
import argparse
import sys
def main(argv):
parser = argparse.ArgumentParser()
parser.add_argument("--arg1", default=False, help="Explain arg1")
parser.add_argument("--arg2", type=str, default="hello", help="Explain arg2")
# add all arguments you need
args = parser.parse_args(argv[1:])
params = {"arg1": args.arg1,
"arg2": args.arg2, }
print(params["arg1"])
print(params["arg2"])
if __name__ == "__main__":
sys.exit(main(sys.argv))

Testing a module with input() and print() inside - using TestCase

Situation:
A students task is to write a python script, doing something with only input() and print().
Example task: "Write python script that asks for number 'n' and prints string of 'n' stars."
He writes a script like this:
solution.py
n = int(input())
print('*' * n)
I want to write python module, that tests that his script is working correctly.
My solution till now is to do this:
test.py
from io import StringIO
import sys
sys.stdout = StringIO()
sys.stdin = StringIO(str(2))
import riesenie
s = sys.stdout.getvalue()
if s != '**' * 2 + '\n':
raise Exception('WRONG')
else:
print("OK", file=sys.stderr)
BUT, I would like to achieve this behaviour using TestCase. Something like:
test.py
from unittest import TestCase
class TestSolution(TestCase):
def test_stars(self):
sys.stdout = StringIO()
sys.stdin = StringIO(str(2))
import riesenie
s = sys.stdout.getvalue()
self.assertEqual('**', s)
But this is not working.
Is there a way to achieve this? Thank you in advance.

Scapy: Inserting a new layer and logging issues

I am attempting to insert GRErouting layer in between GRE and IP using Scapy. The pcap I am reading contains a single packet stacked as follows: Ethernet/IPv4/GRE/IPv4/ICMP.
What I see is that getLayer returns the current layer + its payload, which may include other layers, and that's not good for me. I would like to only get the current layer. When I do getLayer for each layer, and then write the entire array I get a strange pcap because of the additional payload that each layer has over it.
I am also not able to use a simple 'print' to output any data to console. I understand this is because Scapy adds the logging module, and suppresses system logging, but I'd like to know how to undo that and be able to use the 'print' statement.
import os
import sys
import logging
logging.basicConfig()
logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
from scapy.all import PcapReader, PcapWriter, fuzz, Packet
from scapy.layers.l2 import GRE, GRErouting
from scapy.layers.inet import IP
logging.getLogger("scapy.runtime").setLevel(logging.DEBUG)
logging.getLogger().setLevel(logging.DEBUG)
def foo(in_filename, out_filename):
f = PcapReader(in_filename)
o = PcapWriter(out_filename)
p = f.read_packet()
while p:
layers = []
counter = 0
while True:
layer = p.getlayer(counter)
if (layer != None):
layers.append(layer)
if (type(layer) is IP):
del layer.chksum
if (type(layer) is GRE):
logging.getLogger().debug("there is a GRE layer")
layer.routing_present = 1
gr = GRErouting()
fuzz(gr)
layers.append(gr)
del layer.chksum
else:
break
counter += 1
logging.getLogger().debug("Layers are: %s\t\t",layers)
for l in layers:
logging.getLogger().debug("%s", l)
o.write(layers)
p = f.read_packet()
f.close()
o.close()
if __name__ == "__main__":
logging.getLogger().debug('Executing main')
if (len(sys.argv) == 3):
in_filename = str(sys.argv[1])
out_filename = str(sys.argv[2])
if os.path.exists(in_filename) == False:
sys.stderr.write("Either {0} does not exist, or you do not have proper permissions\n".format(in_filename))
else:
foo(in_filename, out_filename)
else:
sys.stderr.write("USAGE: {0} <path to input file> <path to output file>\n".format(str(sys.argv[0])))
I was finally able to answer my own two questions. See modified code below:
# importing the os package (see api at http://docs.python.org/2.6/library/io.html)
import os
# import function 'basename' from module os.path
from os.path import basename
# importing the sys package (see api at http://docs.python.org/2.6/library/sys.html)
import sys
# importing the logging package (see api at http://docs.python.org/2.6/library/logging.html)
import logging
# by default Scapy attempts to find ipv6 routing information,
# and if it does not find any it prints out a warning when running the module.
# the following statement changes log level to ERROR so that this warning will not
# occur
effective_level = logging.getLogger("scapy.runtime").getEffectiveLevel()
logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
# importing Scapy
from scapy.all import PcapReader, PcapWriter
from scapy.layers.l2 import GRE, GRErouting, NoPayload
# return the log level o be what it was
logging.getLogger("scapy.runtime").setLevel(effective_level)
# unfortunately, somewhere in Scapy sys.stdout is being reset.
# thus, using the 'print' command will not produce output to the console.
# the following two lines place stdout back into sys.
if sys.stdout != sys.__stdout__:
sys.stdout = sys.__stdout__
# this is a function declaration. there is no need for explicit types.
# python can infer an object type from its usage
def foo(in_filename, out_filename):
# open the input file for reading
f = PcapReader(in_filename)
# open the output file for writing
o = PcapWriter(out_filename)
# read the first packet from the input file
p = f.read_packet()
# while we haven't processed the last packet
while p:
# gets the first layer of the current packet
layer = p.firstlayer()
# loop over the layers
while not isinstance(layer, NoPayload):
if layer.default_fields.has_key('chksum'):
del layer.chksum
if layer.default_fields.has_key('len'):
del layer.len
if (type(layer) is GRE):
layer.routing_present = 1
layer.chksum_present = 1
# make sure to delete the checksum field. hopefully scapy will calculate it correctly one day
del layer.chksum
gr = GRErouting()
gr.address_family = 0x0800
gr.SRE_len = 4
gr.SRE_offset = 0
gr.routing_info = "1111"
# the NULL routing field
empty_gr = GRErouting()
empty_gr.address_family = 0x0000
empty_gr.SRE_len = 0
gr.add_payload(empty_gr)
gr.add_payload(layer.payload)
layer.remove_payload()
layer.add_payload(gr)
layer = empty_gr
# advance to the next layer
layer = layer.payload
# write the packet we just dissected into the output file
o.write(p)
# read the next packet
p = f.read_packet()
# close the input file
f.close()
# close the output file
o.close()
# i believe this is needed only if we are running the this module
# as the main module. i don't know if this will get executed if this module
# is imported into some other main module
if __name__ == "__main__":
# letting the user know we are starting.
# sys.argv[0] includes the path to the module, including the module name.
# convert sys.argv[0] into string, and extract the module name only
# (using basename)
print '===> Running', basename(str(sys.argv[0]))
# making sure that two parameters were entered on the command line
if (len(sys.argv) == 3):
# get the path to the input file
in_filename = str(sys.argv[1])
# get the path to the output file
out_filename = str(sys.argv[2])
# make sure the input file actually exists.
# if it doesn't, we print out an error and exit
if os.path.exists(in_filename) == False:
# note the method for entering conversion specifiers ({<ordinal>})
sys.stderr.write("Either {0} does not exist, or you do not have proper permissions\n".format(in_filename))
else:
# if the input file does exist, execute 'foo'
foo(in_filename, out_filename)
# print an end script notification
print basename(str(sys.argv[0])), '===> completed successfully'
else:
# write a USAGE message to the standard output stream
sys.stderr.write("USAGE: {0} <path to input file> <path to output file>\n".format(basename(str(sys.argv[0]))))

Resources