1. Open Server Manager
2. Select Roles; right click -> Add Roles and Add Roles Wizard appears
3. In Add Roles Wizard: select Web Server (IIS) in Server Roles page and click Next
4. In Role Services page: select desired services (e.g. ISAPI extensions if IIS should host Axis2/C web service). Click Next.
5. Summary of role features and services that will be installed is displayed. Click Install.
Upon successful installation, a new node named Web Server (IIS) should appear under Roles in Server Manager.
No restart is needed and IIS service will start running automatically. To test whether IIS works, type http://localhost/ in your browser. IIS7 Welcome picture(png) should appear.
Wednesday 21 September 2011
How to get processor architecture information on Windows
Is your machine 32-bit or 64-bit?
One way of getting this information is reading PROCESSOR_ARCHITECTURE value which can be found in Windows Registry at this location: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment.
This value on my 32-bit Intel machine is x86 and on another 64-bit machine with Intel Xeon processor is AMD64.
One way of getting this information is reading PROCESSOR_ARCHITECTURE value which can be found in Windows Registry at this location: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment.
This value on my 32-bit Intel machine is x86 and on another 64-bit machine with Intel Xeon processor is AMD64.
64-bit vs 32-bit
Processors, installed operating systems and applications can be 32-bit or 64-bit. OS needs processor support (64-bit OS requires 64-bit processor) and Application needs operating system support (64-bit application requires 64-bit OS). Backwards compatibility is preserved (32-bit OS runs on 64-bit processor; 32-bit application runs on 64-bit OS).
Here is a short review of all possible combinations:
Backward compatibility is not preserved in kernel mode: 32-bit drivers won't work on 64-bit OS!
It is possible to build applications that target 64-bit architectures on 32-bit hosts. This process is called cross-compiling.
Here is a short review of all possible combinations:
Operating System | |||||
32 | 64 | ||||
P r o c | 32 | OK | x | 32 | A p p |
x | x | 64 | |||
64 | x | OK | |||
OK | OK | 32 |
Backward compatibility is not preserved in kernel mode: 32-bit drivers won't work on 64-bit OS!
- 32-bit applications can run both on 32-bit and 64-bit operating systems. 64-bit Windows OS uses WoW64 emulation layer to support executing 32-bit applications which are, by default, installed in C:\Program Files (x86) directory, load 32-bit libraries from C:\Windows\SysWOW64 and use HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node portion of the registry.
- 64-bit applications can run only on 64-bit operating systems. It is possible to run 64-bit operating system on (physically) 32-bit machine (by using some of Virtual Machines, e.g. Oracle's VirtualBox).
It is possible to build applications that target 64-bit architectures on 32-bit hosts. This process is called cross-compiling.
DOS script which outputs directory contents into a txt file
This simple batch file prints out (recursively, including subdirectories) the content of the current directory into a text file:
list_all_files.bat:
dir * lists the content of the current directory. /b switch makes it to use bare format (report does not include heading information or summary). /s instructs it to use recursion. >temp.txt instructs it to output report to temp.txt file.
After running it, this is the content of temp.txt:
Links and references:
Microsoft DOS dir command
list_all_files.bat:
dir /b /s * >temp.txt
dir * lists the content of the current directory. /b switch makes it to use bare format (report does not include heading information or summary). /s instructs it to use recursion. >temp.txt instructs it to output report to temp.txt file.
After running it, this is the content of temp.txt:
C:\test\list_all_files.bat
C:\test\mydir
C:\test\temp.txt
C:\test\mydir\a.txt
C:\test\mydir
C:\test\temp.txt
C:\test\mydir\a.txt
Links and references:
Microsoft DOS dir command
Monday 19 September 2011
Message only window (MFC)
As expected: message only window cannot post messages to its "parent". CWnd::PostMessage() invoked on HWND_MESSAGE crashes with access violation:
Links and references:
Message-Only Windows (MSDN)
How to make a Message Only Window
How to create a hidden window in C++
class CMsgOnlyWnd : public CWnd
{
...
public:
Initialize();
SendMsgToParent();
...
}
CMsgOnlyWnd::Initialize()
{
...
CreateEx(0, ::AfxRegisterWndClass(NULL), "MsgOnlyWnd", 0, 0, 0, 0, 0, HWND_MESSAGE, 0, NULL);
...
}
CMsgOnlyWnd::SendMsgToParent()
{
GetParent()->PostMessage(...);
}
{
...
public:
Initialize();
SendMsgToParent();
...
}
CMsgOnlyWnd::Initialize()
{
...
CreateEx(0, ::AfxRegisterWndClass(NULL), "MsgOnlyWnd", 0, 0, 0, 0, 0, HWND_MESSAGE, 0, NULL);
...
}
CMsgOnlyWnd::SendMsgToParent()
{
GetParent()->PostMessage(...);
}
Links and references:
Message-Only Windows (MSDN)
How to make a Message Only Window
How to create a hidden window in C++
MFC File dialog
GUI applications use File dialog to allow user to select file in order to perform some operation on it. MFC offers ready to use CFileDialog class (declared in afxdlgs.h).
It is possible to define a filter for file types that will appear in Files list box. File types are listed in combo box which is located at the bottom of the dialog. Filter is defined with a string made of string couples. First string in a couple is the one that will appear in the dialog's combo box and the second one is the extension itself. All string items are separated with vertical tab and the filter string must end with two vertical tabs.
This code will add two items in file type filter combo box:
EXE Files (*.exe)
CAB Files (*.cab)
If we define filter as:
MyApp Setup Files (*.exe;*.cab)
Filter defined as:
EXE Files (*.exe)
All Files (*.*)
Two useful methods of this class are:
CFileDialog allows selecting file either on a local machine or from a shared directory on a network. In the latter case path returned by GetPathName() is a network path (starting with \\remote_host_name\shared_dir\...).
It is possible to define a filter for file types that will appear in Files list box. File types are listed in combo box which is located at the bottom of the dialog. Filter is defined with a string made of string couples. First string in a couple is the one that will appear in the dialog's combo box and the second one is the extension itself. All string items are separated with vertical tab and the filter string must end with two vertical tabs.
This code will add two items in file type filter combo box:
EXE Files (*.exe)
CAB Files (*.cab)
char pszFilter[] = {"EXE Files (*.exe)|*.exe|CAB Files (*.cab)|*.cab||"};
CFileDialog FileDlg(TRUE, ".exe", NULL, 0, pszFilter);
if(FileDlg.DoModal() == IDOK)
{
CString strSelectedFileFullPath(FileDlg.GetPathName());
CString strSelectedFileName(FileDlg.GetFileName());
...
}
else
{
...
}
CFileDialog FileDlg(TRUE, ".exe", NULL, 0, pszFilter);
if(FileDlg.DoModal() == IDOK)
{
CString strSelectedFileFullPath(FileDlg.GetPathName());
CString strSelectedFileName(FileDlg.GetFileName());
...
}
else
{
...
}
If we define filter as:
char pszFilter[] = {"MyApp Setup Files (*.exe;*.cab)|*.exe;*.cab||"};
only exe and cab files will appear in file list box and combo box will have a single item: MyApp Setup Files (*.exe;*.cab)
Filter defined as:
char pszFilter[] = {"EXE Files (*.exe)|*.exe|All Files (*.*)|*.*||"};
adds two items to combo box:EXE Files (*.exe)
All Files (*.*)
Two useful methods of this class are:
- GetPathName() - returns full path to the selected file (including file name)
- GetFileName() - returns a name of the selected file
CFileDialog allows selecting file either on a local machine or from a shared directory on a network. In the latter case path returned by GetPathName() is a network path (starting with \\remote_host_name\shared_dir\...).
Thursday 15 September 2011
How to create a SOAP request
So you know there's a web service deployed on some web server and you want to make a web service call. One way of achieving this is to create SOAP message, put it in a body of HTTP POST command and send it (via TCP/IP) to that web server. If you are using some of web service frameworks (e.g. Apache Axis), you don't need to know the structure of SOAP message; you'll just be adding its elements through dedicated framework functions. But if you don't want to rely on such frameworks, be prepared for creating and parsing SOAP messages by yourself! You can use some HTTP framework (e.g. Microsoft's WinHTTP) to create HTTP POST request and then insert your SOAP request in HTTP message body. Or, you can go one level down and create TCP socket, manually build SOAP and HTTP messages and send them over TCP connection...In this article I'll focus on SOAP messages only.
SOAP (Simple Object Access Protocol) is defined by World Wide Web Consortium (W3C) and the specification of its latest version can be found here.
Paragraph 5 ("SOAP Message Construct") states that SOAP message is represented with one element, named Envelope, from a namespace "http://www.w3.org/2003/05/soap-envelope". XML namespace can be referred via its prefix which is like its alias (abbreviation) and can be any string, soapenv in this case:
Prefix and local name of an element together make its qualified name (QName). XML parser uses the prefix to find the actual namespace URI.
Following examples are using different namespace prefixes but they all refer to the same URI where namespace is defined:
Apart from its local name and namespace, Envelope element contains:
namespace-qualified means that node's name is made of namespace prefix and a local name.
One of the possible attributes determines which encoding should be used to deserialize this message. Its name must contain namespace part (envelope's namespace) and its local name - encodingStyle. Its value is URI of schema that defines encoding:
SOAP Header element contains:
Let us assume that web service has method add which accepts two arguments - two integers - and returns their sum. It would expect to receive XML element like this:
Client should send this element within Body part of SOAP message which could be, in its simplest form (containing only mandatory nodes), like this:
SOAP (Simple Object Access Protocol) is defined by World Wide Web Consortium (W3C) and the specification of its latest version can be found here.
Paragraph 5 ("SOAP Message Construct") states that SOAP message is represented with one element, named Envelope, from a namespace "http://www.w3.org/2003/05/soap-envelope". XML namespace can be referred via its prefix which is like its alias (abbreviation) and can be any string, soapenv in this case:
<soapenv:envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope">
...
</soapenv:envelope>
...
</soapenv:envelope>
Prefix and local name of an element together make its qualified name (QName). XML parser uses the prefix to find the actual namespace URI.
Following examples are using different namespace prefixes but they all refer to the same URI where namespace is defined:
<soap:envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
...
</soap:envelope>
...
</soap:envelope>
<soap-env:envelope xmlns:soap-env="http://www.w3.org/2003/05/soap-envelope">
...
</soap-env:envelope>
...
</soap-env:envelope>
<env:envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope">
...
</env:envelope>
...
</env:envelope>
Apart from its local name and namespace, Envelope element contains:
- other namespaces, from other schemas (optional)
- namespace-qualified attributes (optional)
- Header element (optional child)
- Body element (mandatory child)
namespace-qualified means that node's name is made of namespace prefix and a local name.
One of the possible attributes determines which encoding should be used to deserialize this message. Its name must contain namespace part (envelope's namespace) and its local name - encodingStyle. Its value is URI of schema that defines encoding:
<soapenv:envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope"
soapenv:encodingStyle="http://www.w3.org/2003/05/soap-encoding">
...
</soapenv:envelope>
soapenv:encodingStyle="http://www.w3.org/2003/05/soap-encoding">
...
</soapenv:envelope>
SOAP Header element contains:
- its qualified name made up of envelope's namespace and local name Header (mandatory)
- namespace-qualified attributes (optional)
- namespace-qualified SOAP Header Blocks - children elements (optional)
Each Header Block contains:
- local name and namespace (mandatory)
- attributes (optional); any of all of following attributes defined in soapenv namespace:
- encodingStyle
- role
- mustUnderstand
- relay
- its qualified name made up of envelope's namespace and local name Body (mandatory)
- namespace-qualified attributes (including encodingStyle) (optional)
- namespace-qualified children elements (optional)
Let us assume that web service has method add which accepts two arguments - two integers - and returns their sum. It would expect to receive XML element like this:
<add>
<op1>3</op1>
<op2>4</op2>
</add>
<op1>3</op1>
<op2>4</op2>
</add>
Client should send this element within Body part of SOAP message which could be, in its simplest form (containing only mandatory nodes), like this:
<?xml version="1.0"?>
<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope">
<soapenv:Body>
<add>
<op1>3</op1>
<op2>4</op2>
</add>
</soapenv:Body>
</soapenv:Envelope>
<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope">
<soapenv:Body>
<add>
<op1>3</op1>
<op2>4</op2>
</add>
</soapenv:Body>
</soapenv:Envelope>
Web server receives HTTP POST message, extracts SOAP message from its body and forwards it to Web Service which analyses its headers (if any) and extracts XML from its body. It parses XML and extracts web method name and its arguments.
Obviously, both client and service must use the same function and argument names. This can be enforced if they both use XML documents that are associated to (and are validated against) the same XML schema. How to create one for our XML? If we know the valid structure of it (defined here; see W3C XML Schema page), we could do it manually (which is a kind of reverse engineering) but this is not a way to go: it's better using some tool which will generate it for us from a given XML. Microsoft Visual Studio (2008/2010) could be used as such tool: open your XML file in it and select XML->Create Schema from a main menu. It will create XML Schema document file, named after XML file and with extension xsd.
For wstest.xml:
<?xml version="1.0" encoding="utf-8"?>
<add>
<op1>3</op1>
<op2>4</op2>
</add>
<add>
<op1>3</op1>
<op2>4</op2>
</add>
wstest.xsd is output:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeformdefault="unqualified" elementformdefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="add">
<xs:complextype>
<xs:sequence>
<xs:element name="op1" type="xs:unsignedByte"/>
<xs:element name="op2" type="xs:unsignedByte"/>
</xs:sequence>
</xs:complextype>
</xs:element>
</xs:schema>
<xs:schema attributeformdefault="unqualified" elementformdefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="add">
<xs:complextype>
<xs:sequence>
<xs:element name="op1" type="xs:unsignedByte"/>
<xs:element name="op2" type="xs:unsignedByte"/>
</xs:sequence>
</xs:complextype>
</xs:element>
</xs:schema>
In the example above we are not using namespaces which is a bad practice as element/attribute name clashes can occur. Let us write an XML with namespace-qualified names:
<?xml version="1.0" encoding="utf-8"?>
<ns1:add xmlns:ns1="http://www.bk.com/webservices/wstest">
<ns1:op1>3</ns1:op1>
<ns1:op2>4</ns1:op2>
</ns1:add>
<ns1:add xmlns:ns1="http://www.bk.com/webservices/wstest">
<ns1:op1>3</ns1:op1>
<ns1:op2>4</ns1:op2>
</ns1:add>
Its wstest.xsd:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:ns1="http://www.bk.com/webservices/wstest" attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="http://www.bk.com/webservices/wstest" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="add">
<xs:complextype>
<xs:sequence>
<xs:element name="op1" type="xs:unsignedByte"/>
<xs:element name="op2" type="xs:unsignedByte"/>
</xs:sequence>
</xs:complextype>
</xs:element>
</xs:schema>
<xs:schema xmlns:ns1="http://www.bk.com/webservices/wstest" attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="http://www.bk.com/webservices/wstest" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="add">
<xs:complextype>
<xs:sequence>
<xs:element name="op1" type="xs:unsignedByte"/>
<xs:element name="op2" type="xs:unsignedByte"/>
</xs:sequence>
</xs:complextype>
</xs:element>
</xs:schema>
XML schema above defines namespace "http://www.bk.com/webservices/wstest" (look for targetNamespace attribute) and other metadata related to our XML: valid element names ("add", "op1", "op2"), element and value types. It is worth mentioning here that namespace names are just arbitrary strigs, not locations on the web that XML parsers use in order to retrieve any information. We usually use URIs though (in form of URNs or URLs) as that decreases the chance of two namespaces having the same name. XML parsers treat them just like simple strings.
SOAP request which regards this new namespace looks like this:
<?xml version="1.0"?>
<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope">
<soapenv:Body>
<ns1:add xmlns:ns1="http://www.bk.com/webservices/wstest">
<ns1:op1>3</ns1:op1>
<ns1:op2>4</ns1:op2>
</ns1:add>
</soapenv:Body>
</soapenv:Envelope>
<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope">
<soapenv:Body>
<ns1:add xmlns:ns1="http://www.bk.com/webservices/wstest">
<ns1:op1>3</ns1:op1>
<ns1:op2>4</ns1:op2>
</ns1:add>
</soapenv:Body>
</soapenv:Envelope>
Having local names within namespaces still does not make this document valid. XML document is valid only if it meets requirements of the schema with which it has been associated.
XML Schema can be referenced in an XML document by using schemaLocation attribute in document's root element. This attribute is defined in "http://www.w3.org/2001/XMLSchema-instance" namespace (which is traditionally aliased with xsi name) so we need to include this namespace as well.
We can reference our schema in our SOAP request:
<?xml version="1.0"?>
<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.bk.com/webservices/wstest wstest.xsd">
<soapenv:Body>
<ns1:add xmlns:ns1="http://www.bk.com/webservices/wstest">
<ns1:op1>3</ns1:op1>
<ns1:op2>4</ns1:op2>
</ns1:add>
</soapenv:Body>
</soapenv:Envelope>
<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.bk.com/webservices/wstest wstest.xsd">
<soapenv:Body>
<ns1:add xmlns:ns1="http://www.bk.com/webservices/wstest">
<ns1:op1>3</ns1:op1>
<ns1:op2>4</ns1:op2>
</ns1:add>
</soapenv:Body>
</soapenv:Envelope>
There are two forms of referencing schema:
- using relative URL and schema file name which says that the XSD file is in the same directory as the XML document:
xsi:schemaLocation="http://www.bk.com/webservices/wstest wstest.xsd" (used in the example above)
orxsi:schemaLocation="wstest.xsd"
- using absolute URL of XSD:
xsi:schemaLocation="http://www.bk.com/webservices/wstest/wstest.xsd"
If a schema processor finds schema reference in a document, it should try to retrieve the schemas at the locations indicated. When no information is provided at all the schema processor is free to try any method to find a schema.
If our XML document uses simple types, we can use and reference W3C XML Schema in our document. It is bounded to "http://www.w3.org/2001/XMLSchema" namespace whose aliases are traditionally xs (used in this example) and xsd (often used for Microsoft schemas).
<?xml version="1.0"?>
<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<soapenv:Body>
<ns1:add xmlns:ns1="http://www.bk.com/webservices/wstest">
<ns1:op1 xsi:type="xs:int">3</ns1:op1>
<ns1:op2 xsi:type="xs:int">4</ns1:op2>
</ns1:add>
</soapenv:Body>
</soapenv:Envelope>
<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<soapenv:Body>
<ns1:add xmlns:ns1="http://www.bk.com/webservices/wstest">
<ns1:op1 xsi:type="xs:int">3</ns1:op1>
<ns1:op2 xsi:type="xs:int">4</ns1:op2>
</ns1:add>
</soapenv:Body>
</soapenv:Envelope>
There are many tools that generate WSDL documents for given Web Services. WSDL document describes Web Service, lists its public methods and their arguments. It refers XML schema(s) and describes valid XML structure for web method calls. WSDL (and so XML Schemas) is made public so clients can create SOAP requests and validate them. Schema is used by web service to validate incoming SOAP request and then on the client side to validate response.
Links and references:
SOAP Version 1.2 Part 0: Primer
SOAP Version 1.2 Part 1: Messaging Framework
SOAP Version 1.2 Part 2: Adjuncts
SOAP 1.2 Part 3: One-Way MEP
XML Namespaces by Example
XML Tutorial
Creating Extensible Content Models
XML Schema Part 0: Primer
XML Schema Part 1: Structures
XML Schema Part 2: Datatypes
Using W3C XML Schema
XML Schema (O'Reilly eBook)
XML Schema (W3C)
XML schema (Wikipedia)
XML Schema (W3C)(Wikipedia)
XML Schema (XSD) validation tool? (Stack Overflow)
XML namespace (Wikipedia)
XML Namespaces (W3Schools)
XML Namespace Name: URN or URL?
Understanding XML Namespaces (MSDN Magazine)
XPath, XSLT, and other XML Specifications (MSDN Magazine)
XML Namespaces FAQ
The basics of using XML Schema to define elements
Tip: Send and receive SOAP messages with SAAJ
Apache SOAP type mapping, Part 1: Exploring Apache's serialization APIs
SOAP Tutorial (W3Schools)
XML Schema Tutorial (W3Schools)
SoapUser.com
WSDL Essentials
Monday 5 September 2011
How to share Python code with PyDev for Eclipse
Python allows sharing the code between projects. Shared code (classes, functions,...) is grouped by its purpose/nature into modules which are imported into projects. Modules are simple text files containing Python code and they have extension .py. Modules are organized into packages. Package is actually a directory which contains __init__.py file, modules and/or other packages.
Let us create package named common which contains one module, crypto.
This creates following file hierarchy on the disk:
Packages/modules are usually added as subdirectories of src directory. If any other Python project wants to use any package from this project, it needs to add absolute path to common\src to its PYTHONPATH.
File hierarchy on the disk now looks like this:
A new directory - util - has been created and file __init__.py has been automatically added to it. It is empty by default and we can leave it as such. This file marks its parent directory (util) as Python package directory.
Let us add module crypto to util package:
This adds crypto.py file to util directory. Hierarchy on the disk is now:
If path to common\src is added to PYTHONPATH in some Python project, any Python file belonging to it is able to import crypto module from util package by including this line:
PYTHONPATH is project specific and PyDev uses it to locate source files for compiling, running autocompletion and debugging.
Links and references:
How to organize a Python Project?
The Python Tutorial: Modules
Let us create package named common which contains one module, crypto.
File->New->Python Project
Project Name: common
Directory: C:\Users\Bojan\workspace\Python\common
Project type: Python
Grammar version: 2.7
Interpeter: Default
Create 'src' folder and add it to the PYTHONPATH
Project Name: common
Directory: C:\Users\Bojan\workspace\Python\common
Project type: Python
Grammar version: 2.7
Interpeter: Default
Create 'src' folder and add it to the PYTHONPATH
This creates following file hierarchy on the disk:
common
- src (directory)
- .project
- .pydevproject
- src (directory)
- .project
- .pydevproject
Packages/modules are usually added as subdirectories of src directory. If any other Python project wants to use any package from this project, it needs to add absolute path to common\src to its PYTHONPATH.
File->New->PyDev Package
This wizard forces us to pick src folder in some project as Source Folder:
Source Folder: /common/src
Name: util
This wizard forces us to pick src folder in some project as Source Folder:
Source Folder: /common/src
Name: util
File hierarchy on the disk now looks like this:
common
- src (directory)
- util (directory)
- __init__.py
- .project
- .pydevproject
- src (directory)
- util (directory)
- __init__.py
- .project
- .pydevproject
A new directory - util - has been created and file __init__.py has been automatically added to it. It is empty by default and we can leave it as such. This file marks its parent directory (util) as Python package directory.
Let us add module crypto to util package:
File->New->PyDev Module:
Source Folder: /common/src (wizard allows only src directories form Python projects to be selected here)
Package: util (from /common/src)
Name: crypto
Template: empty
Source Folder: /common/src (wizard allows only src directories form Python projects to be selected here)
Package: util (from /common/src)
Name: crypto
Template: empty
This adds crypto.py file to util directory. Hierarchy on the disk is now:
common
- src (directory)
- util (directory)
- __init__.py
- crypto.py
- .project
- .pydevproject
- src (directory)
- util (directory)
- __init__.py
- crypto.py
- .project
- .pydevproject
If path to common\src is added to PYTHONPATH in some Python project, any Python file belonging to it is able to import crypto module from util package by including this line:
from util import crypto
orfrom util.crypto import *
PYTHONPATH is project specific and PyDev uses it to locate source files for compiling, running autocompletion and debugging.
Let's add some function to crypto.py:
import hashlib
def get_md5(file_path):
md5 = hashlib.md5()
with open(file_path,"rb") as f:
for chunk in iter(lambda: f.read(128 * md5.block_size), ''):
md5.update(chunk)
return md5.hexdigest()
def get_md5(file_path):
md5 = hashlib.md5()
with open(file_path,"rb") as f:
for chunk in iter(lambda: f.read(128 * md5.block_size), ''):
md5.update(chunk)
return md5.hexdigest()
Let us create now a new Python project (named md5) which uses get_md5 function from util.crypto module:
File->New->PyDev Project, Name: md5. We now need to add path to desired module to PYTHONPATH for this project: select project name in the Navigator pane; right-click, Properties; select PyDev - PYTHONPATH; select "External Libraries" tab (as we're adding source that does not belong to this workspace); click on "Add source folder" and browse to the common\src directory (e.g. "C:\Users\Bojan\workspace\Python\common\src").
main.py:
import sys
from util.crypto import get_md5
def main():
print get_md5(r"c:\test\foo.exe")
if __name__ == "__main__":
sys.exit(main())
from util.crypto import get_md5
def main():
print get_md5(r"c:\test\foo.exe")
if __name__ == "__main__":
sys.exit(main())
Links and references:
The Python Tutorial: Modules
Friday 2 September 2011
A Beginner's Python Reference
Scope:
Convention is to use four spaces (and no tabs) for each level of indentation
Console output:
Command line arguments:
String literals:
String literals can be enclosed in matching single quotes (') or double quotes (").
String variables:
How to check whether string str is empty?
String concatenation:
Type conversions:
print "i = " + i fails: TypeError: cannot concatenate 'str' and 'int' objects. i needs to be converted to string first:
Logical operators:
not, and, or. (a and b) is evaluated only if a is True. (a or b) is evaluated only if a is False.
Function return values:
Functions can return a single or multiple values.
Return statement is return.
Example when function returns a pair:
How to terminate application and return error code:
How to make application to wait for user to press Enter?
Defining and using a class:
Enumerations
Links and references:
Python v2.7.2 documentation
Dive into Python
Python coding guidelines:
Style Guide for Python Code
Convention is to use four spaces (and no tabs) for each level of indentation
Console output:
print "Hello, world!"
Command line arguments:
import sys
for arg in sys.argv:
print arg
if len(sys.argv) != 5:
print 'Usage: example.exe '
sys.exit(1)
print "First argument: ", sys.argv[1]
print "Second argument: ", sys.argv[2]
print "Third argument: ", sys.argv[3]
print "Fourth argument: ", sys.argv[4]
for arg in sys.argv:
print arg
if len(sys.argv) != 5:
print 'Usage: example.exe '
sys.exit(1)
print "First argument: ", sys.argv[1]
print "Second argument: ", sys.argv[2]
print "Third argument: ", sys.argv[3]
print "Fourth argument: ", sys.argv[4]
String literals:
String literals can be enclosed in matching single quotes (') or double quotes (").
String variables:
How to check whether string str is empty?
if str
String concatenation:
name = 'Bojan'
print "Name:"+name
print "Name:",name
sys.stdout.write(name)
sys.stdout.write("\n")
name += '\n'
sys.stdout.write(name)
sys.stdout.write('\"' + name + '\"')
sys.stdout.write('\n')
Output:print "Name:"+name
print "Name:",name
sys.stdout.write(name)
sys.stdout.write("\n")
name += '\n'
sys.stdout.write(name)
sys.stdout.write('\"' + name + '\"')
sys.stdout.write('\n')
Name:Bojan
Name: Bojan
Bojan
Bojan
"Bojan
"
Name: Bojan
Bojan
Bojan
"Bojan
"
Type conversions:
print "i = " + i fails: TypeError: cannot concatenate 'str' and 'int' objects. i needs to be converted to string first:
str(i)
- converts integer i into stringLogical operators:
not, and, or. (a and b) is evaluated only if a is True. (a or b) is evaluated only if a is False.
Function return values:
Functions can return a single or multiple values.
Return statement is return.
Example when function returns a pair:
drive, tail = os.path.splitdrive(path)
How to terminate application and return error code:
sys.exit(4)
How to make application to wait for user to press Enter?
raw_input('Press Enter...')
Defining and using a class:
class CPerson:
def __init__(self, name = ""):
self.name = name
def print_name(self):
sys.stdout.write(self.name + "\n")
...
person = CPerson()
person.name = "Bojan"
person.print_name()
def __init__(self, name = ""):
self.name = name
def print_name(self):
sys.stdout.write(self.name + "\n")
...
person = CPerson()
person.name = "Bojan"
person.print_name()
Enumerations
class EnumType:
Value1 = 1
Value2 = 2
...
x = EnumType.Value2
[source]Value1 = 1
Value2 = 2
...
x = EnumType.Value2
Links and references:
Python v2.7.2 documentation
Dive into Python
Python coding guidelines:
Style Guide for Python Code
Python Coding Guidelines
Some questions I found interesting as I've just started experimenting with (diving into) Python:
Is it worth learning Python?
Are there any good reasons why I should not use Python?
Some questions I found interesting as I've just started experimenting with (diving into) Python:
Is it worth learning Python?
Are there any good reasons why I should not use Python?
Subscribe to:
Posts (Atom)