A Python library that provides an interface to communicate with IBM hosts: send commands and text, receive output (screens). The library provides the means to do what a human can do using a 3270 emulator.
The library is highly customizable and is built with simplicity in mind.
It is written in Python 3, runs on Linux and Unix-like Operating Systems, and relies on the s3270
utility. So it is required to have the s3270
installed on your system and available on your PATH.
The library allows you to open a telnet connection to an IBM host, and execute a set of instructions as you specified them in your python program.
A simple pip command brings the library to your environment:
pip install p3270
NB: Make sure that you're using the python3 version of the pip command.
Import the client class from the library:
from p3270 import P3270Client
Create a client object specifying a configuration file:
my_client = P3270Client(configFile='my-config.cfg')
It is also possible to create a client object with the config options stated in the code.
my_client = P3270Client(hostName='192.168.100.25', path='c:\\wc3270\\', codePage='cp277')
If the s3270 program is downloaded as a .zip file or otherwise fails to be added to the path when installed, it is possible to state the path when creating the P3270Client.
Connect the client, and you're good to go:
if not my_client.connect():
print('Connection failed !')
exit(1)
# Start sending your commands to the host ...
The configuration file is used to set a bunch of parameters about the client and host interaction. The file has the following format:
<parameter> = <value>
Lines starting with a '#' are considered as comments and therefore ignored. For now the parameters are:
- hostname: The name or IP address of the host to connect to. Default is
localhost
. - port: The port (on the host) to which the client should connect. Default is
23
. - model: Terminal model name. The possible values are:
3278-n
and3279-n
(n
is the model number and can take the value: 2, 3, 4 or 5). The base model 3278 is a green on black 3270 display, whereas 3279 base model is a color 3270 display. Model numbers are used to specify the screen definition (rows and columns) as follows:
Model number | Columns | Rows |
---|---|---|
2 | 80 | 24 |
3 | 80 | 32 |
4 | 80 | 43 |
5 | 132 | 27 |
Default is 3279-2 . |
- traceFile: The file to which communication traces will be directed. If not set traces will not be generated.
- LUName: LU name to use for connection to the host. If it is not set, connection is done with no LU name.
- enableTLS: Enable or not TLS connection to remote hosts(yes or np). Default is no.
- verifyCert: Verify or not the certificate of the remote host (yes or no). Default is yes.
- codePage: The EBCDIC character set to use for communication with the host.
Supported code pages depens on your
s3270
version. The list can be obtained by running the following command on your shell:
# s3270 -v
Default is cp037
.
An example of configuration file would be:
# Target hostname
hostname = 192.168.100.25
# Port
port = 10023
# Model Name: Default 3279-2
model = 3279-2
# TraceFile
traceFile = client.trace
# LU name to use
#LUName = LUPY0001
# EBCDIC character set to use for the host
codePage = cp037
# The file where all the screens should be saved
screensDir = /home/me/projects/python/mainframe/screens/
One configuration file can be shared by multiple clients.
Once the client object (P3270Client class) is created, the following methods can be used to interact with the host.
connect()
:- Description: Connect the client to the host
- Arguments: none
disconnect()
- Description: Disconenct the client from the host
- Arguments: none
endSession()
- Description: End the client session
- Arguments: none
sendEnter()
- Description: Send the Enter key to host
- Arguments: none
sendPF(n)
- Description: Send a PF (Program Function AID) key
- Arguments:
n (int): PF key number.
The number should be in the range 1..24
sendPA(n)
- Description: Send a PA (Program Attention AID) key
- Arguments: n (int): PA key number.
The number should be in the range 1..3
sendBackSpace()
- Description: Send Back space to the host ()
- Arguments: none
sendBackTab()
- Description: Send back Tab to the host (go to start of previous input field)
- Arguments: none
sendTab()
- Description: Send Tab key to the host
- Arguments: none
clearScreen()
- Description: Clear the screen
- Arguments: none
delChar()
- Description: Delete character next to the cursor (ASCII DEL)
- Arguments: none
delField()
- Description: Delete the whole field
- Arguments: none
eraseChar()
- Description: Erase character previous character (ASCII BS)
- Arguments: none
moveCursorDown()
- Description: Move cursor down
- Arguments: none
moveCursorUp()
- Description: Move cursor up
- Arguments: none
moveCursorLeft()
- Description: Move cursor left
- Arguments: none
moveCursorRight()
- Description: Move cursor right
- Arguments: none
moveTo(row, col)
- Description: Move cursor to a specific position
- Arguments:
row (int): Row position to which the cursor should be moved.
col (int): Column position to which the cursor should be moved.
moveToFirstInputField()
- Description: Move cursor to the first input field on the current screen
- Arguments: none
sendText(text)
- Description: Send text to the host
- Arguments:
text (string): The string to send to the host
saveScreen(fileName, dataType)
- Description: Save the current screen to a file
- Arguments:
fileName (string): File name to which the screen will be saved.
If the file does not exist it is created, otherwise it is appended.
Files are saved under the specified name in the directory specified in the parameterscreensDir
of the configuration file. Default:screen
dataType (string): The data type of the captured screen. Supported data types are html, or rtf. Default:html
getScreen()
- Description: Get the actual screen as raw text
- Arguments: none
printScreen()
- Description: Print the current screen to the standard output
- Arguments: none
isConnected()
- Description: Get the connection status of the client
- Arguments: none
readTextAtPosition(row, col, length)
- Description: Reads text at a row,col position and returns it
- Arguments:
row (int): Row position on where to read.
col (int): Column position on where to read.
length (int): How many chars to read
readTextArea(row, col, rows, cols)
- Description: Reads text area at a row,col position and returns it
- Arguments:
row (int): Row position on where to read.
col (int): Column position on where to read.
rows (int): Number of rows to read down from the starting row.
cols (int): Number of columns to read, right from the starting column.
readTextAtPosition(row, col, expected_text)
- Description: Will check at the given coordinates if the text appear or not. Returns true if the text was found, false if not.
- Arguments:
row (int): Row position on where to read.
col (int): Column position on where to read.
expected_text (string): The text to look for
waitForField()
- Description: Will wait for the field to be ready where the cursor is standing
- Arguments: none
trySendTextToField(text, row, col)
- Description: Will try and write the given text at the given position. Once the text is written, it will check if the text is now shown at the screen at that position. Returns true if succeeded, false if not.
- Arguments:
row (int): Row position on where to read.
col (int): Column position on where to read.
text (string): Text to write
All of the above methods return True
if they succeed, and False
otherwise. The only exceptions:
endSession()
, it terminates the emulation session and returnsTrue
in all cases.readTextAtPosition
,readTextArea
,getScreen
all return the text they read.
from p3270 import P3270Client
# Connect and test if connection succeeded or not
if not my_client.connect():
print('Connection failed !')
exit(1)
# Save the home screen to a file called 'home.html'. HTML format is the default.
my_client.saveScreen(fileName='home.html')
# Send user name to the current field (user ID)
my_client.sendText('user1')
# Send TAB key to go to the next field
my_client.sendTab()
# Send the user password to the password field.
my_client.sendText('password1')
# Send Enter key to submit the current screen with field contents
my_client.sendEnter()
# Clear the screen
my_client.clearScreen()
# Send the CICS command 'CEMT INQ TASK' to get running tasks
my_client.sendText('CEMT INQ TASK')
# Submit
my_client.sendEnter()
# Capture the screen
my_client.saveScreen(fileName='tasks.html')
# Go back : PF3 key
my_client.sendPF(3)
# Go back again
my_client.sendPF(3)
# Disconnect from the host
my_client.disconnect()
# End the emulation session
my_client.endSession()
Screens should go to the directory specified in the parameter screensDir
specified in the configuration file.
The library generates some log messages on the file p3270.log. You can adjust th elog level by modifying it directly on the library.
- Fork the project and create a new branch.
- Do some work.
- Commit and push.
- Open a Pull Request.
GPLv3. See the LICENSE file.